<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Chuang</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Chuang"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Chuang"/>
	<updated>2026-06-25T13:50:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Projects_for_new_developers&amp;diff=49188</id>
		<title>Projects for new developers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Projects_for_new_developers&amp;diff=49188"/>
		<updated>2015-12-29T00:19:48Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* Getting started */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GSOC}}&lt;br /&gt;
&lt;br /&gt;
==Getting started==&lt;br /&gt;
&lt;br /&gt;
Moodle uses PHP, JavaScript, SQL and a number of other Web languages, so learning those is a good place to start.&lt;br /&gt;
&lt;br /&gt;
When you have some basic PHP programming skills, you may wish to start learning about how the Moodle code is organised. It is recommended that you complete the [http://dev.moodle.org/course/view.php?id=2 Introduction to Moodle Programming] course on [http://dev.moodle.org/ dev.moodle.org]. To access this you will need to have an account on moodle.org first.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you are looking for projects suggested in the tracker, look for issues with the [https://tracker.moodle.org/issues/?jql=labels%20in%20%28addon_candidate%29 &#039;addon_candidate&#039; label].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you are looking to make a quick contribution, look for tracker issues with marked as [https://tracker.moodle.org/issues/?jql=Difficulty%20%3D%20Easy easy].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Please consider adopting a [https://moodle.org/plugins/browse.php?list=set&amp;amp;id=61 plugin seeking a new maintainer]&#039;&#039;. See the [https://moodle.org/mod/forum/discuss.php?d=260354 Plugins adoption programme].&lt;br /&gt;
&lt;br /&gt;
As you become more involved in Moodle development, you might like to learn more about the [[Coding|coding conventions]] used and how changes to Moodle core code are [[Process|processed]].&lt;br /&gt;
&lt;br /&gt;
==Potential projects==&lt;br /&gt;
&lt;br /&gt;
This evolving page lists possible Moodle projects for new developers derived from community suggestions.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;If you have any ideas for new features in Moodle which might be suitable as projects for new developers, please see [[New feature ideas]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Plagiarism plugin (Moorsp) ===&lt;br /&gt;
&lt;br /&gt;
There are various commercial plugins available that use the Plagiarism API in Moodle, but because these plagiarism systems can require paid subscriptions, testing them can be difficult. I&#039;d like to see a basic plugin developed (called Moorsp) that could be used for testing the Plagiarism API and provides a structure that can be built on in future to add further functionality.&lt;br /&gt;
&lt;br /&gt;
The initial aim of this project is not to develop a new Plagiarism checking tool but to develop a tool that provides complete Behat and unit tests for the Moodle Plagiarism API. &lt;br /&gt;
&lt;br /&gt;
All files uploaded to Moodle are stored on disk using the contenthash of the file as the filename - this means that if a user uploads the exact file multiple times in different locations only one file is stored on disk. The plugin should implement a check to see if the exact file has been submitted to any other courses/activities and display related information if another match has been found.&lt;br /&gt;
&lt;br /&gt;
Existing Plagiarism plugins (turnitin, urkund, compilatio etc) make use of the legacy log feature of the events api - the new plugin should use the new api and not rely on legacy logs.&lt;br /&gt;
&lt;br /&gt;
Deliverables:&lt;br /&gt;
* All Plagiarism API functions should be implemented.&lt;br /&gt;
* Support for Assign, forum and Workshop modules should be implemented.&lt;br /&gt;
* Full Unit test coverage of all plugin functions.&lt;br /&gt;
* Full Behat tests for Assign, forum and workshop modules should be implemented to ensure that all Plagiarism API functions are working as expected.&lt;br /&gt;
* The code should pass 100% of the Moodle codechecking tools to ensure the code meets with Moodle Guidelines.&lt;br /&gt;
* The code should perform well with appropriate use of the Moodle caching tools.&lt;br /&gt;
&lt;br /&gt;
Future Improvements (outside scope of initial project)&lt;br /&gt;
* Add Plagiarism API to the Moodle Glossary plugin.&lt;br /&gt;
* Implement functions that allow the plugin to post content to an external source - a future open source moorsp server that will receive content and generate a similarity report - we may be able to re-purpose some of the code from the old plagiarism_crot plugin to do this.&lt;br /&gt;
&lt;br /&gt;
This project was proposed in previous GSOC years and some useful information is available in the older discussion [http://dev.moodle.org/mod/forum/discuss.php?d=1822 here]&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Skills required&#039;&#039;&#039;: PHP&lt;br /&gt;
:&#039;&#039;&#039;Difficulty level&#039;&#039;&#039;: Medium&lt;br /&gt;
:&#039;&#039;&#039;Possible mentor&#039;&#039;&#039;: [http://moodle.org/user/view.php?id=21591&amp;amp;course=5 Dan Marsden]&lt;br /&gt;
:&#039;&#039;&#039;Message from the mentor&#039;&#039;&#039;: [http://dev.moodle.org/mod/forum/discuss.php?d=2280 Tips for applying to the moorsp project]&lt;br /&gt;
:&#039;&#039;&#039;Initial code structure&#039;&#039;&#039;: [https://github.com/danmarsden/moodle-plagiarism_moorsp]&lt;br /&gt;
&lt;br /&gt;
=== Improved enrol_meta plugin ===&lt;br /&gt;
&lt;br /&gt;
Current enrol_meta plugin provides functionality to automatically synchronise enrolments between two courses. See [https://docs.moodle.org/en/Course_meta_link Course meta link]. Teacher creates an instance of enroment method in the meta course and links it to one child course. Later cron job ensures that any enrolment change in the child course is pushed to the parent. &lt;br /&gt;
&lt;br /&gt;
Unfortunately user interface is very inconvenient. The main problem is inability to bulk select courses and/or order courses on the Enrolment methods page. Plus it lacks important functionality to synchronise suspended/expired enrolments. See the number of highly voted issues MDL-27628, MDL-17929, MDL-32161, MDL-31451&lt;br /&gt;
&lt;br /&gt;
The proposal is to re-write this enrolment plugin completely. One instance of the plugin should allow to link multiple child courses and additionally synchronise each of them with a group in the meta course.  Ideally it should also allow to synchronise all courses in the category. &lt;br /&gt;
&lt;br /&gt;
This project requires development of both user interface (JS) and backend (PHP).&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Skills required&#039;&#039;&#039;: PHP, Javascript (YUI)&lt;br /&gt;
:&#039;&#039;&#039;Difficulty level&#039;&#039;&#039;: Medium&lt;br /&gt;
:&#039;&#039;&#039;Possible mentor&#039;&#039;&#039;: [https://moodle.org/user/profile.php?id=1334243 Marina Glancy]&lt;br /&gt;
&lt;br /&gt;
=== Allow to crop/resize/rotate images when inserting them ===&lt;br /&gt;
&lt;br /&gt;
This project is inspired by MDL-32183. There are two options on how to implement this functionality - as a repository plugin or as an atto plugin. &lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Skills required&#039;&#039;&#039;: Javascript (YUI), PHP&lt;br /&gt;
:&#039;&#039;&#039;Difficulty level&#039;&#039;&#039;: Medium&lt;br /&gt;
:&#039;&#039;&#039;Possible mentor&#039;&#039;&#039;: [https://moodle.org/user/profile.php?id=1334243 Marina Glancy]&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[GSOC]] - describing Moodle&#039;s involvement with Google in their Summer of Code program&lt;br /&gt;
* [http://tracker.moodle.org/secure/IssueNavigator!executeAdvanced.jspa?jqlQuery=type+in+%28%22New+Feature%22%2C+Improvement%29+AND+resolution+%3D+unresolved+ORDER+BY+votes+DESC&amp;amp;runQuery=true&amp;amp;clear=true Popular new feature and improvement requests in Tracker]&lt;br /&gt;
* [[Projects for new developers/Archive|Archive]] of outdated and/or inactive calls for projects&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=SCORM_schema&amp;diff=41550</id>
		<title>SCORM schema</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=SCORM_schema&amp;diff=41550"/>
		<updated>2013-07-24T20:25:04Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* View an activity */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page explains the files involved in displaying a SCORM package - it is mainly useful for developers.&lt;br /&gt;
&lt;br /&gt;
The names of files in the images below are a slightly out of date compared to 2.0, however the concept is still the same.&lt;br /&gt;
&lt;br /&gt;
== How player works ==&lt;br /&gt;
&lt;br /&gt;
[[Image:Scorm1.5schema.gif]]&lt;br /&gt;
&lt;br /&gt;
==Insert and update an activity==&lt;br /&gt;
&lt;br /&gt;
[[Image:Scorm insert update.png]]&lt;br /&gt;
&lt;br /&gt;
==View an activity==&lt;br /&gt;
&lt;br /&gt;
[[Image:Scorm view.png]]&lt;br /&gt;
&lt;br /&gt;
==SCORM Database Tables==&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5.x, there are 11 database tables that are related to SCORM:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm: Include id, course, name, scormtype, reference, intro, introformat, version, maxgrade, grademethod, etc.&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_aicc_session: This is a new table that did not exist in Moodle 2.0.x. Include id, userid, scormid, hacpsession, scoid, scormmode, scormstatus, attempt, lessonstatus, sessiontime, timecreated, timemodified.&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_scoes: has id, scorm, manifest, organization, parent, identifier, launch, etc.&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_scoes_data: has id, scoid, name, and value. That&#039;s it.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_scorm_scoes_track:&#039;&#039;&#039; has id, userid, scormid, scoid, attempt, element, value, timemodified.&lt;br /&gt;
==&amp;gt; For most developers you probably would be interested in this table.&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_mapinfo:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_objective:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_rolluprule:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_rolluprulecond:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_rulecond:&lt;br /&gt;
&lt;br /&gt;
* mdl_scorm_seq_ruleconds:&lt;br /&gt;
&lt;br /&gt;
[[Category:SCORM]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=39185</id>
		<title>User:Wen Hao Chuang</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=39185"/>
		<updated>2013-04-21T08:52:41Z</updated>

		<summary type="html">&lt;p&gt;Chuang: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m one of the Moodle developers / most helpful Moodlers in the Moodle community. Currently I&#039;m working as an &amp;quot;Academic Technology Consultant&amp;quot; at San Francisco State University (full-time), and teaches part-time in the department of Instructional Technology (ITEC).&lt;br /&gt;
&lt;br /&gt;
Feel free to check out my Linkedin page at http://www.linkedin.com/in/wchuang&lt;br /&gt;
&lt;br /&gt;
For more info about me please read my profile on moodle.org&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/user/view.php?id=18123&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Wizard&amp;diff=29921</id>
		<title>Wizard</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Wizard&amp;diff=29921"/>
		<updated>2011-10-05T20:42:44Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* Problem */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ Moodle User Interface Guidelines|Moodle User Interface Guidelines]] &amp;gt; &#039;&#039;&#039;Wizard&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Problem ==&lt;br /&gt;
* Users need to perform a complex task, with which they are not familiar or lack needed domain knowledge &lt;br /&gt;
* The task users need to perform naturally divides into subtasks, and the nature or number of subtasks depends on what is selected in some other (preceding) tasks&lt;br /&gt;
&lt;br /&gt;
== Context ==&lt;br /&gt;
You are designing an UI for users who are not experts at a given task that involves entering a lot of information or making intricate selections that depend on each other. &lt;br /&gt;
== Forces: factors that affect selection ==&lt;br /&gt;
* Unexperienced users may get frustrated&lt;br /&gt;
** if too many choices, dependent on each other, are presented to them at once&lt;br /&gt;
** if they do not have all the background information related to a task &lt;br /&gt;
* Experienced users easily get frustrated&lt;br /&gt;
** if a task they know is split into too many phases &lt;br /&gt;
** if the order they enter data into the application is controlled&lt;br /&gt;
* Any user can be frustrated by lack of control in the process, i.e. not knowing the number of steps left or not being capable of controlling the process (returning back in the process to an earlier screen in case of a misunderstanding or mistake, for example)&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
&lt;br /&gt;
A Wizard, sometimes called an Assistant, is an interface that guides users through a predefined sequence of steps. &lt;br /&gt;
&lt;br /&gt;
=== Elements of a wizard ===&lt;br /&gt;
&lt;br /&gt;
==== Status display ====&lt;br /&gt;
Displays the steps required to complete the wizard, and indicates the step the user is in currently, giving important feedback to the user resulting from their actions, making the application seem responsive.&lt;br /&gt;
&lt;br /&gt;
==== Navigation buttons ====&lt;br /&gt;
* &#039;&#039;&#039;Previous&#039;&#039;&#039;: Whereever it is possible to allow the user to change the selections they have already made, a button labeled &#039;Previous&#039; should be provided. &lt;br /&gt;
** Obviously, the first page of the wizard does not include a previous button, nor do pages which are a result of actions that can not be undone. &lt;br /&gt;
** Unlike one might assume, the Previous button acts as a submit button for the current page, just like the Next button. If the user has made changes on the current page when they decide to return to a previous step, those changes are saved.&lt;br /&gt;
**Provide a Previous button whenever possible to maximize user control. &lt;br /&gt;
* &#039;&#039;&#039;Next&#039;&#039;&#039;: Used for moving to the next step&lt;br /&gt;
** When the next step is to actually start an operation (usually the last step of the wizard), the button is in the same position, but the label is an action verb such as &amp;quot;Start Backup&amp;quot;. This is to let users know that they are doing something that actually has consequences and not just continuing to enter data. If the operation that the user is about to start cannot be undone or is in some other way potentially dangerous, consider adding a javascript warning dialog confirming the user wants to continue.&lt;br /&gt;
* &#039;&#039;&#039;Cancel&#039;&#039;&#039;: If there is a specific page from which the user can be assumed to have arrived to the wizard from, clicking Cancel will return them to this page. If you can not be sure, determine a reasonable default.&lt;br /&gt;
** The Cancel button should in most cases (except in very simple Wizards) have a javascript confirmation dialog associated with it, noting them that all the information they have entered will be lost, and asking them if they really want to continue.&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
The user should be capable of using the browser&#039;s back button normally in a wizard. &lt;br /&gt;
* After pressing the Next button, the user should end up in the step that was before the page  &lt;br /&gt;
* After pressing the Previous button, the user should end up in the step that is after the current step in the wizard&#039;s sequence&lt;br /&gt;
* If the user cannot return to the previous step anymore, the user should be returned to the earliest possible screen, or alternatively the wizard should be reinitialized and the user sent to the first page of the wizard &lt;br /&gt;
&lt;br /&gt;
If there is a danger that experienced users want to use the functionality provided by the wizard and that they want more control than what the wizard provides, provide an alternate user interface to them.&lt;br /&gt;
&lt;br /&gt;
== Common mistakes ==&lt;br /&gt;
&lt;br /&gt;
Moodle Wizards typically do not have all of the required buttons nor the status display.&lt;br /&gt;
&lt;br /&gt;
Each screen is a form, so no links are used for moving between the screens but the next/previous should be used. The added click of selecting a form field and then pressing &#039;next&#039; is secondary to the problem of potentially losing user data: even if the data is preserved (using javascript which cannot be relied upon anyway), navigation links do not afford this so the user is left anxious. Also usage of back/forward browser buttons is problematic if what user has selected is not saved in the session using a the next/prev buttons (which are technically form submit buttons).&lt;br /&gt;
&lt;br /&gt;
== Examples and implementation ==&lt;br /&gt;
&lt;br /&gt;
=== Backup ===&lt;br /&gt;
&lt;br /&gt;
[[Image:wizard-mockup.png|thumb]] &lt;br /&gt;
This mockup (MDL-20036) demonstrates the main features of a wizard. &lt;br /&gt;
* Status display and controls for controlling the wizard&lt;br /&gt;
* The visual hierarchy of the page expresses that the content in the box with the darker background is part of the wizard, and that this wizard is completes the process of backing up the Course Course Fullname 101.&lt;br /&gt;
&lt;br /&gt;
Note that this wizard is in the sense not typical that it only contains one step where the user actually does anything actively (enters information). The fact that the single screen contains a lot of information may slow down novices, but since backup can be considered an advanced operation, slowing down more experienced users would be worse.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Note&#039;&#039;&#039;: Moodle 2.0 contains a implementation of a wizard done according to MDL-20036 (see MDL-22142). View it at http://qa.moodle.net/backup/backup.php?id=1 (requires login with the qa site testing credentials). A screenshot should be added here as soon as Moodle 2.0 is released.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further examples and code samples: [[Wizard Examples and Code Samples]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Related guidelines ==&lt;br /&gt;
Another way of only showing unexperienced users what they understand is using [[Progressive_Disclosure|Progressive Disclosure]]&lt;br /&gt;
&lt;br /&gt;
== Related issues in the tracker ==&lt;br /&gt;
* TODO: all the issues with installation and backup&lt;br /&gt;
&lt;br /&gt;
== (Optional) Further information / Sources  ==&lt;br /&gt;
* GNOME HIG: [http://library.gnome.org/devel/hig-book/stable/windows-assistant.html.en Assistants]&lt;br /&gt;
* http://ui-patterns.com/pattern/Wizard&lt;br /&gt;
* http://www.welie.com/patterns/showPattern.php?patternID=wizard&lt;br /&gt;
* http://uipatternfactory.com/p=wizard/&lt;br /&gt;
* http://en.wikipedia.org/wiki/Wizard_(software)&lt;br /&gt;
&lt;br /&gt;
[[Category:Moodle User Interface Guidelines]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2791</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2791"/>
		<updated>2011-02-24T17:44:24Z</updated>

		<summary type="html">&lt;p&gt;Chuang: minor typo correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; A Step-by-step Guide To Creating Blocks &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Original Author: Jon Papaioannou ([mailto:pj@moodle.org pj@moodle.org])&lt;br /&gt;
&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&lt;br /&gt;
The present document serves as a guide to developers who want to create their own blocks for use in Moodle. It applies to the 1.5 development version of Moodle (and any newer) &#039;&#039;&#039;only&#039;&#039;&#039;, as the blocks subsystem was rewritten and expanded for the 1.5 release. However, you can also find it useful if you want to modify blocks written for Moodle 1.3 and 1.4 to work with the latest versions (look at [[Blocks/Appendix_B| Appendix B]]).&lt;br /&gt;
&lt;br /&gt;
The guide is written as an interactive course which aims to develop a configurable, multi-purpose block that displays arbitrary HTML. It&#039;s targeted mainly at people with little experience with Moodle or programming in general and aims to show how easy it is to create new blocks for Moodle. A certain small amount of PHP programming knowledge is still required, though. &lt;br /&gt;
&lt;br /&gt;
Experienced developers and those who just want a &#039;&#039;&#039;reference&#039;&#039;&#039; text should refer to [[Blocks/Appendix_A| Appendix A]] because the main guide has a rather low concentration of pure information in the text.&lt;br /&gt;
&lt;br /&gt;
== Basic Concepts ==&lt;br /&gt;
&lt;br /&gt;
Through this guide, we will be following the creation of an &amp;quot;HTML&amp;quot; block from scratch in order to demonstrate most of the block features at our disposal. Our block will be named &amp;quot;SimpleHTML&amp;quot;. This does not constrain us regarding the name of the actual directory on the server where the files for our block will be stored, but for consistency we will follow the practice of using the lowercased form &amp;quot;simplehtml&amp;quot; in any case where such a name is required. &lt;br /&gt;
&lt;br /&gt;
Whenever we refer to a file or directory name which contains &amp;quot;simplehtml&amp;quot;, it&#039;s important to remember that &#039;&#039;only&#039;&#039; the &amp;quot;simplehtml&amp;quot; part is up to us to change; the rest is standardized and essential for Moodle to work correctly.&lt;br /&gt;
&lt;br /&gt;
Whenever a file&#039;s path is mentioned in this guide, it will always start with a slash. This refers to the Moodle home directory; all files and directories will be referred to with respect to that directory.&lt;br /&gt;
&lt;br /&gt;
== Ready, Set, Go! ==&lt;br /&gt;
&lt;br /&gt;
To define a &amp;quot;block&amp;quot; in Moodle, in the most basic case we need to provide just one source code file. We start by creating the directory &#039;&#039;/blocks/simplehtml/&#039;&#039; and creating a file named &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; which will hold our code. We then begin coding the block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class block_simplehtml extends block_base {&lt;br /&gt;
  function init() {&lt;br /&gt;
    $this-&amp;gt;title   = get_string(&#039;simplehtml&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    $this-&amp;gt;version = 2004111200;&lt;br /&gt;
  }&lt;br /&gt;
  // The PHP tag and the curly bracket for the class definition &lt;br /&gt;
  // will only be closed after there is another function added in the next section.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line is our block class definition; it must be named exactly in the manner shown. Again, only the &amp;quot;simplehtml&amp;quot; part can (and indeed must) change; everything else is standardized.&lt;br /&gt;
&lt;br /&gt;
Our class is then given a small method: [[Blocks/Appendix_A#init.28.29| init()]]. This is essential for all blocks, and its purpose is to set the two class member variables listed inside it. But what do these values actually mean? Here&#039;s a more detailed description.&lt;br /&gt;
&lt;br /&gt;
[[Blocks/Appendix_A#.24this-.3Etitle| $this-&amp;gt;title]] is the title displayed in the header of our block. We can set it to whatever we like; in this case it&#039;s set to read the actual title from a language file we are presumably distributing together with the block. I &#039;ll skip ahead a bit here and say that if you want your block to display &#039;&#039;&#039;no&#039;&#039;&#039; title at all, then you should set this to any descriptive value you want (but &#039;&#039;&#039;not&#039;&#039;&#039; make it an empty string). We will later see [[Blocks#Eye_Candy| how to disable the title&#039;s display]].&lt;br /&gt;
&lt;br /&gt;
[[Blocks/Appendix_A#.24this-.3Eversion| $this-&amp;gt;version]] is the version of our block. This actually would only make a difference if your block wanted to keep its own data in special tables in the database (i.e. for very complex blocks). In that case the version number is used exactly as it&#039;s used in activities; an upgrade script uses it to incrementally upgrade an &amp;quot;old&amp;quot; version of the block&#039;s data to the latest. We will outline this process further ahead, since blocks tend to be relatively simple and not hold their own private data. &lt;br /&gt;
&lt;br /&gt;
In our example, this is certainly the case so we just set [[Blocks/Appendix_A#.24this-.3Eversion| $this-&amp;gt;version]] to &#039;&#039;&#039;YYYYMMDD00&#039;&#039;&#039; and forget about it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATING:&#039;&#039;&#039;&amp;lt;br /&amp;gt; &lt;br /&gt;
Prior to version 1.5, the basic structure of each block class was slightly different. Refer to [[Blocks/Appendix_B| Appendix B]] for more information on the changes that old blocks have to make to conform to the new standard.&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
If you are using Moodle 2.0 and starting to develop your own block. You have to put the version information of the block in a separate file named version.php in &#039;&#039;/blocks/simplehtml/&#039;&#039;&#039;&#039;&#039;version.php&#039;&#039;&#039;. This file has no reference in its name or content to the block&#039;s name (simplehtml).&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 will also require a name for your plugin to show in the upgrading page. You set this value in a language package (the same file where you put your string for the plugin title). Create the file &#039;&#039;/blocks/simplehtml/lang/en/&#039;&#039;&#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; and paste the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
  $string[&#039;pluginname&#039;] = &#039;Simple html block&#039;;&lt;br /&gt;
  $string[&#039;simplehtml&#039;] = &#039;Simple html&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I Just Hear Static ==&lt;br /&gt;
In order to get our block to actually display something on screen, we need to add one more method to our class (before the final closing brace in our file). The new code is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;  &lt;br /&gt;
  function get_content() {&lt;br /&gt;
    if ($this-&amp;gt;content !== NULL) {&lt;br /&gt;
      return $this-&amp;gt;content;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;content         =  new stdClass;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
}   // Here&#039;s the closing curly bracket for the class definition&lt;br /&gt;
    // and here&#039;s the closing PHP tag from the section above.&lt;br /&gt;
?&amp;gt;  &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It can&#039;t get any simpler than that, can it? Let&#039;s dissect this method to see what&#039;s going on...&lt;br /&gt;
&lt;br /&gt;
First of all, there is a check that returns the current value of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] if it&#039;s not NULL; otherwise we proceed with &amp;quot;computing&amp;quot; it. Since the computation is potentially a time-consuming operation and it &#039;&#039;&#039;will&#039;&#039;&#039; be called several times for each block (Moodle works that way internally), we take a precaution and include this time-saver.&lt;br /&gt;
Supposing the content had not been computed before (it was NULL), we then define it from scratch. The code speaks for itself there, so there isn&#039;t much to say. Just keep in mind that we can use HTML both in the text &#039;&#039;&#039;and&#039;&#039;&#039; in the footer, if we want to.&lt;br /&gt;
&lt;br /&gt;
At this point our block should be capable of being automatically installed in Moodle and added to courses; visit your administration page to install it (Click &amp;quot;Notifications&amp;quot; under the Site Administration Block) and after seeing it in action come back to continue our tutorial.&lt;br /&gt;
&lt;br /&gt;
== Configure That Out ==&lt;br /&gt;
&lt;br /&gt;
The current version of our block doesn&#039;t really do much; it just displays a fixed message, which is not very useful. What we &#039;d really like to do is allow the teachers to customize what goes into the block. This, in block-speak, is called &amp;quot;instance configuration&amp;quot;. So let&#039;s give our block some instance configuration...&lt;br /&gt;
First of all, we need to tell Moodle that we want it to provide instance-specific configuration amenities to our block. That&#039;s as simple as adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function instance_allow_config() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This small change is enough to make Moodle display an &amp;quot;Edit...&amp;quot; icon in our block&#039;s header when we turn editing mode on in any course. However, if you try to click on that icon you will be presented with a notice that complains about the block&#039;s configuration not being implemented correctly. Try it, it&#039;s harmless.&lt;br /&gt;
Moodle&#039;s complaints do make sense. We told it that we want to have configuration, but we didn&#039;t say &#039;&#039;what&#039;&#039; kind of configuration we want, or how it should be displayed. To do that, we need to create one more file: &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;config_instance.html&#039;&#039;&#039;&amp;lt;/span&amp;gt; (which has to be named exactly like that). For the moment, copy paste the following into it and save:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;table cellpadding=&amp;quot;9&amp;quot; cellspacing=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;td align=&amp;quot;right&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;?php print_string(&#039;configcontent&#039;, &#039;block_simplehtml&#039;); ?&amp;gt;:&lt;br /&gt;
    &amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&lt;br /&gt;
       &amp;lt;?php print_textarea(true, 10, 50, 0, 0, &#039;text&#039;, $this-&amp;gt;config-&amp;gt;text); ?&amp;gt;&lt;br /&gt;
    &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td colspan=&amp;quot;2&amp;quot; align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;&amp;lt;?php print_string(&#039;savechanges&#039;) ?&amp;gt;&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;?php use_html_editor(); ?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It isn&#039;t difficult to see that the above code just provides us with a wysiwyg-editor-enabled textarea to write our block&#039;s desired content in and a submit button to save. But... what&#039;s $this-&amp;gt;config-&amp;gt;text? Well...&lt;br /&gt;
Moodle goes a long way to make things easier for block developers. Did you notice that the textarea is actually named &amp;quot;text&amp;quot;? When the submit button is pressed, Moodle saves each and every field it can find in our &#039;&#039;&#039;config_instance.html&#039;&#039;&#039; file as instance configuration data. &lt;br /&gt;
&lt;br /&gt;
We can then access that data as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;&#039;&#039;variablename&#039;&#039;&#039;&#039;&#039;, where &#039;&#039;variablename&#039;&#039; is the actual name we used for our field; in this case, &amp;quot;text&amp;quot;. So in essence, the above form just pre-populates the textarea with the current content of the block (as indeed it should) and then allows us to change it.&lt;br /&gt;
&lt;br /&gt;
You also might be surprised by the presence of a submit button and the absence of any &amp;lt;form&amp;gt; element at the same time. But the truth is, we don&#039;t need to worry about that at all; Moodle goes a really long way to make things easier for developers! We just print the configuration options we want, in any format we want; include a submit button, and Moodle will handle all the rest itself. The instance configuration variables are automatically at our disposal to access from any of the class methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29| init()]].&lt;br /&gt;
&lt;br /&gt;
In the event where the default behaviour is not satisfactory, we can still override it. However, this requires advanced modifications to our block class and will not be covered here; refer to [[Blocks/Appendix_A| Appendix A]] for more details.&lt;br /&gt;
Having now the ability to refer to this instance configuration data through [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]], the final twist is to tell our block to actually &#039;&#039;display&#039;&#039; what is saved in its configuration data. To do that, find this snippet in &#039;&#039;/blocks/simplehtml/block_simplehtml.php&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;content = new stdClass;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;text   = &#039;The content of our SimpleHTML block!&#039;;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and change it to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;content = new stdClass;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;text   = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oh, and since the footer isn&#039;t really exciting at this point, we remove it from our block because it doesn&#039;t contribute anything. We could just as easily have decided to make the footer configurable in the above way, too. So for our latest code, the snippet becomes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;content = new stdClass;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;text   = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
 $this-&amp;gt;content-&amp;gt;footer = &#039;&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After this discussion, our block is ready for prime time! Indeed, if you now visit any course with a SimpleHTML block, you will see that modifying its contents is now a snap.&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.0 there is a simpler way to create the interface to configure your block. Instead of creating the &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;config_instance.html&#039;&#039;&#039;&amp;lt;/span&amp;gt; file, you have to create a &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/&#039;&#039;&#039;edit_form.php&#039;&#039;&#039;&amp;lt;/span&amp;gt; file which contains only php code and no HTML. Moodle will process this file and add its elements to the configuration page for your block.&lt;br /&gt;
&lt;br /&gt;
Create the edit_form.php file and paste the following code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class block_simplehtml_edit_form extends block_edit_form {&lt;br /&gt;
	&lt;br /&gt;
    protected function specific_definition($mform) {&lt;br /&gt;
    	&lt;br /&gt;
        // Section header title according to language file.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;configheader&#039;, get_string(&#039;blocksettings&#039;, &#039;block&#039;));&lt;br /&gt;
&lt;br /&gt;
        // A sample string variable with a default value.&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;config_text&#039;, get_string(&#039;blockstring&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;config_text&#039;, &#039;default value&#039;);&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;config_text&#039;, PARAM_MULTILANG);        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The first line declares a class that inherits from block_edit_form, this allows Moodle to identify the code to execute in the configuration page. The specific_definition function does two things: It indicates the header for the configuration section, which in this case we took from the &#039;blocksettings&#039; string for blocks. The second part is where you define the variables that will be defined in the config part of your block. Three lines define this: The first one adds an element, each element is a variable within config, that is of text type, and is described by the blockstring string in the language file for the simplehtml block. The second line indicates a default value (in case it is not yet defined). The third line sets a type for our variable, in this case PARAM_MULTILANG.&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Specialists ==&lt;br /&gt;
&lt;br /&gt;
Implementing instance configuration for the block&#039;s contents was good enough to whet our appetite, but who wants to stop there? Why not customize the block&#039;s title, too?&lt;br /&gt;
&lt;br /&gt;
Why not, indeed. Well, our first attempt to achieve this is natural enough: let&#039;s add another field to &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/config_instance.html&amp;lt;/span&amp;gt;. Here goes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;tr valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;td align=&amp;quot;right&amp;quot;&amp;gt;&amp;lt;p&amp;gt;&lt;br /&gt;
    &amp;lt;?php print_string(&#039;configtitle&#039;, &#039;block_simplehtml&#039;); ?&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;td&amp;gt;&lt;br /&gt;
    &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;title&amp;quot; size=&amp;quot;30&amp;quot; value=&amp;quot;&amp;lt;?php echo $this-&amp;gt;config-&amp;gt;title; ?&amp;gt;&amp;quot; /&amp;gt;&lt;br /&gt;
  &amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We save the edited file, go to a course, edit the title of the block and... nothing happens! The instance configuration is saved correctly, all right (editing it once more proves that) but it&#039;s not being displayed. All we get is just the simple &amp;quot;SimpleHTML&amp;quot; title.&lt;br /&gt;
&lt;br /&gt;
That&#039;s not too weird, if we think back a bit. Do you remember that [[Blocks/Appendix_A#init.28.29|init()]] method, where we set [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]]? We didn&#039;t actually change its value from then, and [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] is definitely not the same as &#039;&#039;&#039;$this-&amp;gt;config-&amp;gt;title&#039;&#039;&#039; (to Moodle, at least). What we need is a way to update [[Blocks/Appendix_A#.24this-.3Etitle|$this-&amp;gt;title]] with the value in the instance configuration. But as we said a bit earlier, we can use [[Blocks/Appendix_A#.24this-.3Econfig| $this-&amp;gt;config]] in all methods &#039;&#039;except&#039;&#039; [[Blocks/Appendix_A#init.28.29|init()]]! So what can we do?&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pull out another ace from our sleeve, and add this small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function specialization() {&lt;br /&gt;
  if (!empty($this-&amp;gt;config-&amp;gt;title)) {&lt;br /&gt;
    $this-&amp;gt;title = $this-&amp;gt;config-&amp;gt;title;&lt;br /&gt;
  } else {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;title = &#039;Some title ...&#039;;&lt;br /&gt;
  }&lt;br /&gt;
  if (empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;config-&amp;gt;text = &#039;Some text ...&#039;;&lt;br /&gt;
  }    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aha, here&#039;s what we wanted to do all along! But what&#039;s going on with the [[Blocks/Appendix_A#specialization.28.29| specialization()]] method?&lt;br /&gt;
&lt;br /&gt;
This &amp;quot;magic&amp;quot; method has actually a very nice property: it&#039;s &#039;&#039;guaranteed&#039;&#039; to be automatically called by Moodle as soon as our instance configuration is loaded and available (that is, immediately after [[Blocks/Appendix_A#init.28.29|init()]] is called). That means before the block&#039;s content is computed for the first time, and indeed before &#039;&#039;anything&#039;&#039; else is done with the block. Thus, providing a [[Blocks/Appendix_A#specialization.28.29| specialization()]] method is the natural choice for any configuration data that needs to be acted upon &amp;quot;as soon as possible&amp;quot;, as in this case.&lt;br /&gt;
&lt;br /&gt;
== Now You See Me, Now You Don&#039;t ==&lt;br /&gt;
&lt;br /&gt;
Now would be a good time to mention another nifty technique that can be used in blocks, and which comes in handy quite often. Specifically, it may be the case that our block will have something interesting to display some of the time; but in some other cases, it won&#039;t have anything useful to say. (An example here would be the &amp;quot;Recent Activity&amp;quot; block, in the case where no recent activity in fact exists. &lt;br /&gt;
&lt;br /&gt;
However in that case the block chooses to explicitly inform you of the lack of said activity, which is arguably useful). It would be nice, then, to be able to have our block &amp;quot;disappear&amp;quot; if it&#039;s not needed to display it.&lt;br /&gt;
&lt;br /&gt;
This is indeed possible, and the way to do it is to make sure that after the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called, the block is completely void of content. Specifically, &amp;quot;void of content&amp;quot; means that both $this-&amp;gt;content-&amp;gt;text and $this-&amp;gt;content-&amp;gt;footer are each equal to the empty string (&amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;). Moodle performs this check by calling the block&#039;s [[Blocks/Appendix_A#is_empty.28.29| is_empty()]] method, and if the block is indeed empty then it is not displayed at all.&lt;br /&gt;
&lt;br /&gt;
Note that the exact value of the block&#039;s title and the presence or absence of a [[Blocks/Appendix_A#hide_header.28.29| hide_header()]] method do &#039;&#039;not&#039;&#039; affect this behavior. A block is considered empty if it has no content, irrespective of anything else.&lt;br /&gt;
&lt;br /&gt;
== We Are Legion ==&lt;br /&gt;
&lt;br /&gt;
Right now our block is fully configurable, both in title and content. It&#039;s so versatile, in fact, that we could make pretty much anything out of it. It would be really nice to be able to add multiple blocks of this type to a single course. And, as you might have guessed, doing that is as simple as adding another small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function instance_allow_multiple() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells Moodle that it should allow any number of instances of the SimpleHTML block in any course. After saving the changes to our file, Moodle immediately allows us to add multiple copies of the block without further ado!&lt;br /&gt;
&lt;br /&gt;
There are a couple more of interesting points to note here. First of all, even if a block itself allows multiple instances in the same page, the administrator still has the option of disallowing such behavior. This setting can be set separately for each block from the Administration / Configuration / Blocks page.&lt;br /&gt;
&lt;br /&gt;
And finally, a nice detail is that as soon as we defined an [[Blocks/Appendix_A#instance_allow_multiple.28.29| instance_allow_multiple()]] method, the method [[Blocks/Appendix_A#instance_allow_config.28.29| instance_allow_config()]] that was already defined became obsolete. &lt;br /&gt;
&lt;br /&gt;
Moodle assumes that if a block allows multiple instances of itself, those instances will want to be configured (what is the point of same multiple instances in the same page if they are identical?) and thus automatically provides an &amp;quot;Edit&amp;quot; icon. So, we can also remove the whole [[Blocks/Appendix_A#instance_allow_config.28.29| instance_allow_config()]] method now without harm. We had only needed it when multiple instances of the block were not allowed.&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== The Effects of Globalization ==&lt;br /&gt;
&lt;br /&gt;
Configuring each block instance with its own personal data is cool enough, but sometimes administrators need some way to &amp;quot;touch&amp;quot; all instances of a specific block at the same time. In the case of our SimpleHTML block, a few settings that would make sense to apply to all instances aren&#039;t that hard to come up with. &lt;br /&gt;
&lt;br /&gt;
For example, we might want to limit the contents of each block to only so many characters, or we might have a setting that filters HTML out of the block&#039;s contents, only allowing pure text in. Granted, such a feature wouldn&#039;t win us any awards for naming our block &amp;quot;SimpleHTML&amp;quot; but some tormented administrator somewhere might actually find it useful.&lt;br /&gt;
&lt;br /&gt;
This kind of configuration is called &amp;quot;global configuration&amp;quot; and applies only to a specific block type (all instances of that block type are affected, however). Implementing such configuration for our block is quite similar to implementing the instance configuration. We will now see how to implement the second example, having a setting that only allows text and not HTML in the block&#039;s contents.&lt;br /&gt;
First of all, we need to tell Moodle that we want our block to provide global configuration by, what a surprise, adding a small method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function has_config() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need to create a HTML file that actually prints out the configuration screen. In our case, we &#039;ll just print out a checkbox saying &amp;quot;Do not allow HTML in the content&amp;quot; and a &amp;quot;submit&amp;quot; button. Let&#039;s create the file &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/blocks/simplehtml/config_global.html&amp;lt;/span&amp;gt; which again must be named just so, and copy paste the following into it:&lt;br /&gt;
&lt;br /&gt;
[[Development_talk:Blocks|TODO: New settings.php method]] &lt;br /&gt;
: Just to note that general documentation about admin settings is at [[Admin_settings#Individual_settings]]. In the absence of documentation, you can look at blocks/course_list, blocks/online_users and blocks/rss_client. They all use a settings.php file.--[[User:Tim Hunt|Tim Hunt]] 19:38, 28 January 2009 (CST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;block_simplehtml_strict&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;block_simplehtml_strict&amp;quot; value=&amp;quot;1&amp;quot;&lt;br /&gt;
   &amp;lt;?php if(!empty($CFG-&amp;gt;block_simplehtml_strict)) &lt;br /&gt;
             echo &#039;checked=&amp;quot;checked&amp;quot;&#039;; ?&amp;gt; /&amp;gt;&lt;br /&gt;
   &amp;lt;?php print_string(&#039;donotallowhtml&#039;, &#039;block_simplehtml&#039;); ?&amp;gt;&lt;br /&gt;
 &amp;lt;p&amp;gt;&lt;br /&gt;
 &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;&amp;lt;?php print_string(&#039;savechanges&#039;); ?&amp;gt;&amp;quot; /&amp;gt;&lt;br /&gt;
 &amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
True to our block&#039;s name, this looks simple enough. What it does is that it displays a checkbox named &amp;quot;block_simplehtml_strict&amp;quot; and if the Moodle configuration variable with the same name (i.e., $CFG-&amp;gt;block_simplehtml_strict) is set and not empty (that means it&#039;s not equal to an empty string, to zero, or to boolean FALSE) it displays the box as pre-checked (reflecting the current status). &lt;br /&gt;
&lt;br /&gt;
Why does it check the configuration setting with the same name? Because the default implementation of the global configuration saving code takes all the variables we have in our form and saves them as Moodle configuration options with the same name. Thus, it&#039;s good practice to use a descriptive name and also one that won&#039;t possibly conflict with the name of another setting. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;block_simplehtml_strict&amp;quot; clearly satisfies both requirements.&lt;br /&gt;
&lt;br /&gt;
The astute reader may have noticed that we actually have &#039;&#039;two&#039;&#039; input fields named &amp;quot;block_simplehtml_strict&amp;quot; in our configuration file. One is hidden and its value is always 0; the other is the checkbox and its value is 1. What gives? Why have them both there?&lt;br /&gt;
&lt;br /&gt;
Actually, this is a small trick we use to make our job as simple as possible. HTML forms work this way: if a checkbox in a form is not checked, its name does not appear at all in the variables passed to PHP when the form is submitted. That effectively means that, when we uncheck the box and click submit, the variable is not passed to PHP at all. Thus, PHP does not know to update its value to &amp;quot;0&amp;quot;, and our &amp;quot;strict&amp;quot; setting cannot be turned off at all once we turn it on for the first time. Not the behavior we want, surely.&lt;br /&gt;
&lt;br /&gt;
However, when PHP handles received variables from a form, the variables are processed in the order in which they appear in the form. If a variable comes up having the same name with an already-processed variable, the new value overwrites the old one. Taking advantage of this, our logic runs as follows: the variable &amp;quot;block_simplehtml_strict&amp;quot; is first unconditionally set to &amp;quot;0&amp;quot;. Then, &#039;&#039;if&#039;&#039; the box is checked, it is set to &amp;quot;1&amp;quot;, overwriting the previous value as discussed. The net result is that our configuration setting behaves as it should.&lt;br /&gt;
&lt;br /&gt;
To round our bag of tricks up, notice that the use of &#039;&#039;if(!empty($CFG-&amp;gt;block_simplehtml_strict))&#039;&#039; in the test for &amp;quot;should the box be checked by default?&amp;quot; is quite deliberate. The first time this script runs, the variable &#039;&#039;&#039;$CFG-&amp;gt;block_simplehtml_strict&#039;&#039;&#039; will not exist at all. After it&#039;s set for the first time, its value can be either &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot;. Given that both &amp;quot;not set&amp;quot; and the string &amp;quot;0&amp;quot; evaluate as empty while the sting &amp;quot;1&amp;quot; does not, we manage to avoid any warnings from PHP regarding the variable not being set at all, &#039;&#039;and&#039;&#039; have a nice human-readable representation for its two possible values (&amp;quot;0&amp;quot; and &amp;quot;1&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== config_save() ===&lt;br /&gt;
&lt;br /&gt;
Now that we have managed to cram a respectable amount of tricks into a few lines of HTML, we might as well discuss the alternative in case that tricks are not enough for a specific configuration setup we have in mind. Saving the data is done in the method [[Blocks/Appendix_A#config_save.28.29| config_save()]], the default implementation of which is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function config_save($data) {&lt;br /&gt;
  // Default behavior: save all variables as $CFG properties&lt;br /&gt;
  foreach ($data as $name =&amp;gt; $value) {&lt;br /&gt;
    set_config($name, $value);&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As can be clearly seen, Moodle passes this method an associative array $data which contains all the variables coming in from our configuration screen. If we wanted to do the job without the &amp;quot;hidden variable with the same name&amp;quot; trick we used above, one way to do it would be by overriding this method with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function config_save($data) {&lt;br /&gt;
  if(isset($data[&#039;block_simplehtml_strict&#039;])) {&lt;br /&gt;
    set_config(&#039;block_simplehtml_strict&#039;, &#039;1&#039;);&lt;br /&gt;
  }else {&lt;br /&gt;
    set_config(&#039;block_simplehtml_strict&#039;, &#039;0&#039;);&lt;br /&gt;
  }&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quite straightfoward: if the variable &amp;quot;block_simplehtml_strict&amp;quot; is passed to us, then it can only mean that the user has checked it, so set the configuration variable with the same name to &amp;quot;1&amp;quot;. Otherwise, set it to &amp;quot;0&amp;quot;. Of course, this version would need to be updated if we add more configuration options because it doesn&#039;t respond to them as the default implementation does. Still, it&#039;s useful to know how we can override the default implementation if it does not fit our needs (for example, we might not want to save the variable as part of the Moodle configuration but do something else with it).&lt;br /&gt;
&lt;br /&gt;
So, we are now at the point where we know if the block should allow HTML tags in its content or not. How do we get the block to actually respect that setting?&lt;br /&gt;
&lt;br /&gt;
We could decide to do one of two things: either have the block &amp;quot;clean&amp;quot; HTML out from the input before saving it in the instance configuration and then display it as-is (the &amp;quot;eager&amp;quot; approach); or have it save the data &amp;quot;as is&amp;quot; and then clean it up each time just before displaying it (the &amp;quot;lazy&amp;quot; approach). The eager approach involves doing work once when saving the configuration; the lazy approach means doing work each time the block is displayed and thus it promises to be worse performance-wise. We shall hence go with the eager approach.&lt;br /&gt;
&lt;br /&gt;
===String me up ===&lt;br /&gt;
&lt;br /&gt;
Now that we have a working config_global with saved values we want to be able to read the values from it. The simplest way to do this is to assign the config setting to a string and then use the string as we would any other. IE;&lt;br /&gt;
&lt;br /&gt;
$string = $CFG-&amp;gt;configsetting;&lt;br /&gt;
&lt;br /&gt;
You can check all the configuration settings available to a module by displaying them all with;&lt;br /&gt;
&lt;br /&gt;
print_object($CFG);  &lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
=== instance_config_save() ===&lt;br /&gt;
&lt;br /&gt;
Much as we did just before with overriding [[Blocks/Appendix_A#config_save.28.29| config_save()]], what is needed here is overriding the method [[Blocks/Appendix_A#instance_config_save.28.29| instance_config_save()]] which handles the instance configuration. The default implementation is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function instance_config_save($data) {&lt;br /&gt;
  $data = stripslashes_recursive($data);&lt;br /&gt;
  $this-&amp;gt;config = $data;&lt;br /&gt;
  return set_field(&#039;block_instance&#039;, &lt;br /&gt;
                   &#039;configdata&#039;,&lt;br /&gt;
                    base64_encode(serialize($data)),&lt;br /&gt;
                   &#039;id&#039;, &lt;br /&gt;
                   $this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This may look intimidating at first (what&#039;s all this stripslashes_recursive() and base64_encode() and serialize() stuff?) but do not despair; we won&#039;t have to touch any of it. We will only add some extra validation code in the beginning and then instruct Moodle to additionally call this default implementation to do the actual storing of the data. Specifically, we will add a method to our class which goes like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function instance_config_save($data) {&lt;br /&gt;
  // Clean the data if we have to&lt;br /&gt;
  global $CFG;&lt;br /&gt;
  if(!empty($CFG-&amp;gt;block_simplehtml_strict)) {&lt;br /&gt;
    $data-&amp;gt;text = strip_tags($data-&amp;gt;text);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // And now forward to the default implementation defined in the parent class&lt;br /&gt;
  return parent::instance_config_save($data);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At last! Now the administrator has absolute power of life and death over what type of content is allowed in our &amp;quot;SimpleHTML&amp;quot; block! Absolute? Well... not exactly. In fact, if we think about it for a while, it will become apparent that if at some point in time HTML is allowed and some blocks have saved their content with HTML included, and afterwards the administrator changes the setting to &amp;quot;off&amp;quot;, this will only prevent subsequent content changes from including HTML. Blocks which already had HTML in their content would continue to display it!&lt;br /&gt;
&lt;br /&gt;
Following that train of thought, the next stop is realizing that we wouldn&#039;t have this problem if we had chosen the lazy approach a while back, because in that case we would &amp;quot;sanitize&amp;quot; each block&#039;s content just before it was displayed. &lt;br /&gt;
&lt;br /&gt;
The only thing we can do with the eager approach is strip all the tags from the content of all SimpleHTML instances as soon as the admin setting is changed to &amp;quot;HTML off&amp;quot;; but even then, turning the setting back to &amp;quot;HTML on&amp;quot; won&#039;t bring back the tags we stripped away. On the other hand, the lazy approach might be slower, but it&#039;s more versatile; we can choose whether to strip or keep the HTML before displaying the content, and we won&#039;t lose it at all if the admin toggles the setting off and on again. Isn&#039;t the life of a developer simple and wonderful?&lt;br /&gt;
&lt;br /&gt;
=== Exercise === &lt;br /&gt;
We will let this part of the tutorial come to a close with the obligatory exercise for the reader: &lt;br /&gt;
In order to have the SimpleHTML block work &amp;quot;correctly&amp;quot;, find out how to strengthen the eager approach to strip out all tags from the existing configuration of all instances of our block, &#039;&#039;&#039;or&#039;&#039;&#039; go back and implement the lazy approach instead. &lt;br /&gt;
(Hint: Do that in the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method.)&lt;br /&gt;
&lt;br /&gt;
=== UPDATING: === &lt;br /&gt;
Prior to version 1.5, the file &#039;&#039;config_global.html&#039;&#039; was named simply &#039;&#039;config.html&#039;&#039;. Also, the methods [[Blocks_Howto#method_config_save| config_save]] and [[Blocks_Howto#method_config_print| config_print]] were named &#039;&#039;&#039;handle_config&#039;&#039;&#039; and &#039;&#039;&#039;print_config&#039;&#039;&#039; respectively. Upgrading a block to work with Moodle 1.5 involves updating these aspects; refer to [[Blocks_Howto#appendix_b| Appendix B]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Eye Candy ==&lt;br /&gt;
&lt;br /&gt;
Our block is just about complete functionally, so now let&#039;s take a look at some of the tricks we can use to make its behavior customized in a few more useful ways.&lt;br /&gt;
&lt;br /&gt;
First of all, there are a couple of ways we can adjust the visual aspects of our block. For starters, it might be useful to create a block that doesn&#039;t display a header (title) at all. You can see this effect in action in the Course Description block that comes with Moodle. This behavior is achieved by, you guessed it, adding one more method to our block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function hide_header() {&lt;br /&gt;
  return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One more note here: we cannot just set an empty title inside the block&#039;s [[Blocks/Appendix_A#init.28.29| init()]] method; it&#039;s necessary for each block to have a unique, non-empty title after [[Blocks/Appendix_A#init.28.29| init()]] is called so that Moodle can use those titles to differentiate between all of the installed blocks.&lt;br /&gt;
&lt;br /&gt;
Another adjustment we might want to do is instruct our block to take up a certain amount of width on screen. Moodle handles this as a two-part process: first, it queries each block about its preferred width and takes the maximum number as the desired value. Then, the page that&#039;s being displayed can choose to use this value or, more probably, bring it within some specific range of values if it isn&#039;t already. That means that the width setting is a best-effort settlement; your block can &#039;&#039;request&#039;&#039; a certain width and Moodle will &#039;&#039;try&#039;&#039; to provide it, but there&#039;s no guarantee whatsoever about the end result. As a concrete example, all standard Moodle course formats will deliver any requested width between 180 and 210 pixels, inclusive.&lt;br /&gt;
&lt;br /&gt;
To instruct Moodle about our block&#039;s preferred width, we add one more method to the block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function preferred_width() {&lt;br /&gt;
  // The preferred value is in pixels&lt;br /&gt;
  return 200;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
This will make our block (and all the other blocks displayed at the same side of the page) a bit wider than standard.&lt;br /&gt;
&lt;br /&gt;
Finally, we can also affect some properties of the actual HTML that will be used to print our block. Each block is fully contained within a &amp;amp;lt;div&amp;amp;gt; or &amp;amp;lt;table&amp;amp;gt; elements, inside which all the HTML for that block is printed. We can instruct Moodle to add HTML attributes with specific values to that container. This would be done to either a) directly affect the end result (if we say, assign bgcolor=&amp;quot;black&amp;quot;), or b) give us freedom to customize the end result using CSS (this is in fact done by default as we&#039;ll see below).&lt;br /&gt;
&lt;br /&gt;
The default behavior of this feature in our case will assign to our block&#039;s container the class HTML attribute with the value &amp;quot;sideblock block_simplehtml&amp;quot; (the prefix &amp;quot;block_&amp;quot; followed by the name of our block, lowercased). We can then use that class to make CSS selectors in our theme to alter this block&#039;s visual style (for example, &amp;quot;.sideblock.block_simplehtml { border: 1px black solid}&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
To change the default behavior, we will need to define a method which returns an associative array of attribute names and values. For example, the version&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function html_attributes() {&lt;br /&gt;
  return array(&lt;br /&gt;
    &#039;class&#039;       =&amp;gt; &#039;sideblock block_&#039;. $this-&amp;gt;name(),&lt;br /&gt;
    &#039;onmouseover&#039; =&amp;gt; &amp;quot;alert(&#039;Mouseover on our block!&#039;);&amp;quot;&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will result in a mouseover event being added to our block using JavaScript, just as if we had written the onmouseover=&amp;quot;alert(...)&amp;quot; part ourselves in HTML. Note that we actually duplicate the part which sets the class attribute (we want to keep that, and since we override the default behavior it&#039;s our responsibility to emulate it if required). &lt;br /&gt;
&lt;br /&gt;
And the final elegant touch is that we don&#039;t set the class to the hard-coded value &amp;quot;block_simplehtml&amp;quot; but instead use the [[Blocks/Appendix_A#name.28.29| name()]] method to make it dynamically match our block&#039;s name.&lt;br /&gt;
&lt;br /&gt;
===and some other useful examples too:===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function html_attributes() {&lt;br /&gt;
    // Default case: an id with the instance and a class with our name in it&lt;br /&gt;
    return array(&#039;id&#039; =&amp;gt; &#039;inst&#039;.$this-&amp;gt;instance-&amp;gt;id, &#039;class&#039; =&amp;gt; &#039;block_&#039;. $this-&amp;gt;name());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method should return an associative array of HTML attributes that will be given to your block&#039;s container element when Moodle constructs the output HTML. No sanitization will be performed in these elements at all.&lt;br /&gt;
&lt;br /&gt;
If you intend to override this method, you should return the default attributes as well as those you add yourself. The recommended way to do this is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function html_attributes() {&lt;br /&gt;
    $attrs = parent::html_attributes();&lt;br /&gt;
    // Add your own attributes here, e.g.&lt;br /&gt;
    // $attrs[&#039;width&#039;] = &#039;50%&#039;;&lt;br /&gt;
    return $attrs;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authorized Personnel Only ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s not difficult to imagine a block which is very useful in some circumstances but it simply cannot be made meaningful in others. An example of this would be the &amp;quot;Social Activities&amp;quot; block which is indeed useful in a course with the social format, but doesn&#039;t do anything useful in a course with the weeks format. There should be some way of allowing the use of such blocks only where they are indeed meaningful, and not letting them confuse users if they are not.&lt;br /&gt;
&lt;br /&gt;
Moodle allows us to declare which course formats each block is allowed to be displayed in, and enforces these restrictions as set by the block developers at all times. The information is given to Moodle as a standard associative array, with each key corresponding to a page format and defining a boolean value (true/false) that declares whether the block should be allowed to appear in that page format.&lt;br /&gt;
&lt;br /&gt;
Notice the deliberate use of the term &#039;&#039;page&#039;&#039; instead of &#039;&#039;course&#039;&#039; in the above paragraph. This is because in Moodle 1.5 and onwards, blocks can be displayed in any page that supports them. The best example of such pages are the course pages, but we are not restricted to them. For instance, the quiz view page (the first one we see when we click on the name of the quiz) also supports blocks.&lt;br /&gt;
&lt;br /&gt;
The format names we can use for the pages derive from the name of the script which is actually used to display that page. For example, when we are looking at a course, the script is &amp;lt;span class=&amp;quot;filename&amp;quot;&amp;gt;/course/view.php&amp;lt;/span&amp;gt; (this is evident from the browser&#039;s address line). Thus, the format name of that page is &#039;&#039;&#039;course-view&#039;&#039;&#039;. It follows easily that the format name for a quiz view page is &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039;. This rule of thumb does have a few exceptions, however:&lt;br /&gt;
&lt;br /&gt;
# The format name for the front page of Moodle is &#039;&#039;&#039;site-index&#039;&#039;&#039;.&lt;br /&gt;
# The format name for courses is actually not just &#039;&#039;&#039;course-view&#039;&#039;&#039;&amp;lt;nowiki&amp;gt;; it is &amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;course-view-weeks&#039;&#039;&#039;, &#039;&#039;&#039;course-view-topics&#039;&#039;&#039;, etc.&lt;br /&gt;
# Even though there is no such page, the format name &#039;&#039;&#039;all&#039;&#039;&#039; can be used as a catch-all option.&lt;br /&gt;
&lt;br /&gt;
We can include as many format names as we want in our definition of the applicable formats. Each format can be allowed or disallowed, and there are also three more rules that help resolve the question &amp;quot;is this block allowed into this page or not?&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
# Prefixes of a format name will match that format name; for example, &#039;&#039;&#039;mod&#039;&#039;&#039; will match all the activity modules. &#039;&#039;&#039;course-view&#039;&#039;&#039; will match any course, regardless of the course format. And finally, &#039;&#039;&#039;site&#039;&#039;&#039; will also match the front page (remember that its full format name is &#039;&#039;&#039;site-index&#039;&#039;&#039;).&lt;br /&gt;
# The more specialized a format name that matches our page is, the higher precedence it has when deciding if the block will be allowed. For example, &#039;&#039;&#039;mod&#039;&#039;&#039;, &#039;&#039;&#039;mod-quiz&#039;&#039;&#039; and &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; all match the quiz view page. But if all three are present, &#039;&#039;&#039;mod-quiz-view&#039;&#039;&#039; will take precedence over the other two because it is a better match.&lt;br /&gt;
# The character &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; can be used in place of any word. For example, &#039;&#039;&#039;mod&#039;&#039;&#039; and &#039;&#039;&#039;mod-*&#039;&#039;&#039; are equivalent. At the time of this document&#039;s writing, there is no actual reason to utilize this &amp;quot;wildcard matching&amp;quot; feature, but it exists for future usage.&lt;br /&gt;
# The order that the format names appear does not make any difference.&lt;br /&gt;
All of the above are enough to make the situation sound complex, so let&#039;s look at some specific examples. First of all, to have our block appear &#039;&#039;&#039;only&#039;&#039;&#039; in the site front page, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function applicable_formats() {&lt;br /&gt;
  return array(&#039;site&#039; =&amp;gt; true);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Since &#039;&#039;&#039;all&#039;&#039;&#039; is missing, the block is disallowed from appearing in &#039;&#039;any&#039;&#039; course format; but then &#039;&#039;&#039;site&#039;&#039;&#039; is set to TRUE, so it&#039;s explicitly allowed to appear in the site front page (remember that &#039;&#039;&#039;site&#039;&#039;&#039; matches &#039;&#039;&#039;site-index&#039;&#039;&#039; because it&#039;s a prefix).&lt;br /&gt;
&lt;br /&gt;
For another example, if we wanted to allow the block to appear in all course formats &#039;&#039;except&#039;&#039; social, and also to &#039;&#039;not&#039;&#039; be allowed anywhere but in courses, we would use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
    &#039;course-view-social&#039; =&amp;gt; false);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time, we first allow the block to appear in all courses and then we explicitly disallow the social format.&lt;br /&gt;
For our final, most complicated example, suppose that a block can be displayed in the site front page, in courses (but not social courses) and also when we are viewing any activity module, &#039;&#039;except&#039;&#039; quiz. This would be:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function applicable_formats() {&lt;br /&gt;
  return array(&lt;br /&gt;
           &#039;site-index&#039; =&amp;gt; true,&lt;br /&gt;
          &#039;course-view&#039; =&amp;gt; true, &lt;br /&gt;
   &#039;course-view-social&#039; =&amp;gt; false,&lt;br /&gt;
                  &#039;mod&#039; =&amp;gt; true, &lt;br /&gt;
             &#039;mod-quiz&#039; =&amp;gt; false&lt;br /&gt;
  );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is not difficult to realize that the above accomplishes the objective if we remember that there is a &amp;quot;best match&amp;quot; policy to determine the end result.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPDATING:&#039;&#039;&#039; &amp;lt;br /&amp;gt;&lt;br /&gt;
Prior to version 1.5, blocks were only allowed in courses (and in Moodle 1.4, in the site front page). Also, the keywords used to describe the valid course formats at the time were slightly different and had to be changed in order to allow for a more open architecture. Refer to [[Blocks/Appendix_B| Appendix B]] for more information on the changes that old blocks have to make to conform to the new standard.&lt;br /&gt;
&lt;br /&gt;
== Responding to Cron ==&lt;br /&gt;
&lt;br /&gt;
It is possible to have your block respond to the cron process. That is have a method that is run at regular intervals regardless of user interaction. There are two parts to this. Firstly you need to define a new function within your block class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function cron() {&lt;br /&gt;
    mtrace( &amp;quot;Hey, my cron script is running&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // do something&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then within your init function you will need to set the (minimum) execution interval for your cron function. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $this-&amp;gt;cron = 300;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Will set the minimum interval to 5 minutes. However, the function can only be called as frequently as cron has been set to run in the Moodle installation. Remember that if you change any values in the init function you &#039;&#039;&#039;must&#039;&#039;&#039; bump the version number and visit the Notifications page otherwise they will be ignored.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039;&lt;br /&gt;
The block cron is designed to call the cron script for that block &#039;&#039;&#039;type&#039;&#039;&#039; only. That is, cron does not care about individual instances of blocks. Inside your cron function although $this is defined it has almost nothing in it (only title, content type, version and cron fields are populated). If you need to execute cron for individual instances it is your own responsibility to iterate over them in the block&#039;s cron function. Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function cron() {&lt;br /&gt;
&lt;br /&gt;
    // get the block type from the name&lt;br /&gt;
    $blocktype = get_record( &#039;block&#039;, &#039;name&#039;, &#039;my_block_name&#039; );&lt;br /&gt;
&lt;br /&gt;
    // get the instances of the block&lt;br /&gt;
    $instances = get_records( &#039;block_instance&#039;,&#039;blockid&#039;,$blocktype-&amp;gt;id );&lt;br /&gt;
&lt;br /&gt;
    // iterate over the instances&lt;br /&gt;
    foreach ($instances as $instance) {&lt;br /&gt;
&lt;br /&gt;
        // recreate block object&lt;br /&gt;
        $block = block_instance( &#039;my_block_name&#039;, $instance );&lt;br /&gt;
&lt;br /&gt;
        // $block is now the equivalent of $this in &#039;normal&#039; block&lt;br /&gt;
        // usage, e.g.&lt;br /&gt;
        $someconfigitem = $block-&amp;gt;config-&amp;gt;item2;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;my_block_name&#039; will coincide with the name of the directory the block is stored in.&lt;br /&gt;
&lt;br /&gt;
TIP: This also means that creating a block is a possible way to create code that can respond to cron with a reasonably low overhead. No actual instances of the block are required.&lt;br /&gt;
&lt;br /&gt;
== Lists and Icons ==&lt;br /&gt;
&lt;br /&gt;
In this final part of the guide we will briefly discuss an additional capability of Moodle&#039;s block system, namely the ability to very easily create blocks that display a list of choices to the user. This list is displayed with one item per line, and an optional image (icon) next to the item. An example of such a &#039;&#039;list block&#039;&#039; is the standard Moodle &amp;quot;admin&amp;quot; block, which illustrates all the points discussed in this section.&lt;br /&gt;
&lt;br /&gt;
As we have seen so far, blocks use two properties of [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]]: &amp;quot;text&amp;quot; and &amp;quot;footer&amp;quot;. The text is displayed as-is as the block content, and the footer is displayed below the content in a smaller font size. List blocks use $this-&amp;gt;content-&amp;gt;footer in the exact same way, but they ignore $this-&amp;gt;content-&amp;gt;text.&lt;br /&gt;
&lt;br /&gt;
Instead, Moodle expects such blocks to set two other properties when the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method is called: $this-&amp;gt;content-&amp;gt;items and $this-&amp;gt;content-&amp;gt;icons. $this-&amp;gt;content-&amp;gt;items should be a numerically indexed array containing elements that represent the HTML for each item in the list that is going to be displayed. Usually these items will be HTML anchor tags which provide links to some page. $this-&amp;gt;content-&amp;gt;icons should also be a numerically indexed array, with exactly as many items as $this-&amp;gt;content-&amp;gt;items has. Each of these items should be a fully qualified HTML &amp;lt;img&amp;gt; tag, with &amp;quot;src&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;width&amp;quot; and &amp;quot;alt&amp;quot; attributes. Obviously, it makes sense to keep the images small and of a uniform size.&lt;br /&gt;
&lt;br /&gt;
In order to tell Moodle that we want to have a list block instead of the standard text block, we need to make a small change to our block class declaration. Instead of extending class &#039;&#039;&#039;block_base&#039;&#039;&#039;, our block will extend class &#039;&#039;&#039;block_list&#039;&#039;&#039;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
 class block_my_menu extends block_list {&lt;br /&gt;
     // The init() method does not need to change at all&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition to making this change, we must of course also modify the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method to construct the [[Blocks/Appendix_A#.24this-.3Econtent| $this-&amp;gt;content]] variable as discussed above:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function get_content() {&lt;br /&gt;
  if ($this-&amp;gt;content !== null) {&lt;br /&gt;
    return $this-&amp;gt;content;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content         = new stdClass;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons  = array();&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
 &lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;items[] = &#039;&amp;lt;a href=&amp;quot;some_file.php&amp;quot;&amp;gt;Menu Option 1&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
  $this-&amp;gt;content-&amp;gt;icons[] = &#039;&amp;lt;img src=&amp;quot;images/icons/1.gif&amp;quot; class=&amp;quot;icon&amp;quot; alt=&amp;quot;&amp;quot; /&amp;gt;&#039;;&lt;br /&gt;
 &lt;br /&gt;
  // Add more list items here&lt;br /&gt;
 &lt;br /&gt;
  return $this-&amp;gt;content;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To summarize, if we want to create a list block instead of a text block, we just need to change the block class declaration and the [[Blocks/Appendix_A#get_content.28.29| get_content()]] method. Adding the mandatory [[Blocks/Appendix_A#init.28.29| init()]] method as discussed earlier will then give us our first list block in no time!&lt;br /&gt;
&lt;br /&gt;
{{Top}}&lt;br /&gt;
&lt;br /&gt;
== Database support ==&lt;br /&gt;
In case you need to have a database table that holds some specific information that is used with your block. you will need to create a sub folder &#039;&#039;&#039;db&#039;&#039;&#039; and have an &#039;&#039;&#039;install.xml&#039;&#039;&#039; file with the table schema setup.&lt;br /&gt;
&lt;br /&gt;
To create the install.xml file, use the [[XMLDB editor]]. See [[Database_FAQ#XMLDB|Database FAQ &amp;gt; XMLDB]] for further details.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [http://dev.moodle.org/mod/resource/view.php?id=48 Unit 7 of the Introduction to Moodle Programming course] is a follow up to this course. (But you should follow the forum discussions of that course closely as there are still some bugs and inconsistencies.)&lt;br /&gt;
* A [http://cvs.moodle.org/contrib/plugins/blocks/NEWBLOCK/ NEWBLOCK template] you can all use to start you own block.&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
; Moodle 2.0&lt;br /&gt;
* See [[Migrating contrib code to 2.0]] and [[User:Frank Ralf/Experience of converting a module to Moodle 2]] for information on relevant changes for Moodle 2.0.&lt;br /&gt;
&lt;br /&gt;
== Appendices ==&lt;br /&gt;
&lt;br /&gt;
The appendices have been moved to separate pages:&lt;br /&gt;
&lt;br /&gt;
* Appendix A: [[Blocks/Appendix A|&#039;&#039;block_base&#039;&#039; Reference]] &lt;br /&gt;
* Appendix B: [[Blocks/Appendix B|Differences in the Blocks API for Moodle Versions prior to 1.5]]&lt;br /&gt;
* Appendix C: [[Blocks/Appendix C|Creating Database Tables for Blocks (prior to 1.7)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;br /&gt;
[[ja:開発:ブロック]]&lt;br /&gt;
[[ru:Development:Blocks]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=20435</id>
		<title>User:Wen Hao Chuang</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=20435"/>
		<updated>2010-08-23T23:22:16Z</updated>

		<summary type="html">&lt;p&gt;Chuang: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m one of the Moodle developers / most helpful Moodlers in the Moodle community. Currently I&#039;m working as an &amp;quot;Academic Technology Consultant&amp;quot; at San Francisco State University (full-time), and teaches part-time in the department of Instructional Technology (ITEC).&lt;br /&gt;
&lt;br /&gt;
Feel free to check out my personal website (very much outdated) at http://userwww.sfsu.edu/~wchuang&lt;br /&gt;
&lt;br /&gt;
For more info about me please read my profile on moodle.org&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/user/view.php?id=18123&amp;amp;course=1&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=20434</id>
		<title>User:Wen Hao Chuang</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Wen_Hao_Chuang&amp;diff=20434"/>
		<updated>2008-02-27T22:10:45Z</updated>

		<summary type="html">&lt;p&gt;Chuang: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For more info about me please read my profile on moodle.org&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/user/view.php?id=18123&amp;amp;course=1&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Wen_Hao_Chuang&amp;diff=23689</id>
		<title>User talk:Wen Hao Chuang</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Wen_Hao_Chuang&amp;diff=23689"/>
		<updated>2008-02-27T07:25:00Z</updated>

		<summary type="html">&lt;p&gt;Chuang: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is my &amp;quot;User talk&amp;quot; page. For more information about me please read my profile on moodle.org:&lt;br /&gt;
&lt;br /&gt;
http://moodle.org/user/view.php?id=18123&amp;amp;course=5&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Unit_test_API&amp;diff=3942</id>
		<title>Unit test API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Unit_test_API&amp;diff=3942"/>
		<updated>2007-12-16T10:08:56Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* Access to global variables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The purpose of unit testing is to test the individual parts of the program (functions, and methods of classes) to make sure that each individually does the right thing. Once unit testing has given you the confidence that each part works, then you should use other forms of testing to ensure that the different parts work together properly.&lt;br /&gt;
&lt;br /&gt;
The unit testing framework is based on the [http://www.lastcraft.com/simple_test.php SimpleTest] framework. It was incorporated into Moodle by Nick Freear and Tim Hunt from [http://www.open.ac.uk/ The Open University].&lt;br /&gt;
&lt;br /&gt;
== Running the unit tests in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Running the basic tests ===&lt;br /&gt;
&lt;br /&gt;
# Log in with an admin account. &lt;br /&gt;
# Go to the admin screen.&lt;br /&gt;
# Click on the &#039;&#039;&#039;Reports&#039;&#039;&#039; link near the bottom of the page.&lt;br /&gt;
# Click on the &#039;&#039;&#039;Run the unit tests&#039;&#039;&#039; link.&lt;br /&gt;
# Wait for the tests to run.&lt;br /&gt;
&lt;br /&gt;
=== Options for running the tests ===&lt;br /&gt;
&lt;br /&gt;
At the bottom of the tests page, there is form that lets you adjust the options used when running the tests.&lt;br /&gt;
&lt;br /&gt;
==== Show passes as well as fails ====&lt;br /&gt;
&lt;br /&gt;
Normally, only details of the tests that have failed are printed. Turning on this options shows details of all the passes too.&lt;br /&gt;
&lt;br /&gt;
==== Show the search for test files ====&lt;br /&gt;
&lt;br /&gt;
The tests to run are found automatically be searching the codebase for files whose names match &#039;&#039;&#039;test*.php&#039;&#039;&#039; in directories called &#039;&#039;&#039;simpletest&#039;&#039;&#039;. Turning on this option will print a list of the folders searched and the test files found. This is sometimes useful for debugging.&lt;br /&gt;
&lt;br /&gt;
This option is particularly useful when one of your test files has a syntax error. When this happens, you sometimes just get a blank page with no error message. Turning on the show search option lets you see which test file it was that gave the error. If necessary, you can enable this option manually by adding &amp;quot;showsearch=1&amp;quot; to the end of the URL.&lt;br /&gt;
&lt;br /&gt;
==== Run a thorough test (may be slow) ====&lt;br /&gt;
&lt;br /&gt;
If you turn on this option, then as well as looking for files called &#039;&#039;&#039;test*.php&#039;&#039;&#039;, the search also looks for files called &#039;&#039;&#039;slowtest*.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
To be useful, the full test run should find most bugs, but not take too long to complete. So if you have very, very detailed tests of an area of the code, it may be better to select a subset for everday testing, and only use the more detailed tests when a bug is reported, or you are doing new development in that area of the code.&lt;br /&gt;
&lt;br /&gt;
This option is most useful when combined with the next option.&lt;br /&gt;
&lt;br /&gt;
==== Only run tests in ====&lt;br /&gt;
&lt;br /&gt;
Normally, tests from all parts of the codebase are run. However, when you are just doing development of one part of the code, that is a waste of time. You can type the name of a folder (for example &#039;&#039;&#039;mod/quiz&#039;&#039;&#039;) or a particular test file (for example &#039;&#039;&#039;lib/simpletest/testdatalib.php&#039;&#039;&#039;) and then only those tests will be run.&lt;br /&gt;
&lt;br /&gt;
[[Image:RunOnlyTheseTests.png|right]] Instead of typing a path into this box, there is an easier way. Whenever a pass or fail is displayed, the name of the test file is printed. Each section of the path name is a link to run only the tests in that folder or file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Writing new tests ==&lt;br /&gt;
&lt;br /&gt;
As an example, suppose we wanted to start writing tests for the functions in the file &#039;question/editlib.php&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Where to put the tests ===&lt;br /&gt;
&lt;br /&gt;
If you have read the first half of this page and were paying attention, you can probably work out that you should create a folder called &#039;&#039;&#039;question/testeditlib&#039;&#039;&#039;, and create a file in there called something like &#039;&#039;&#039;testeditlib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The skeleton of this file should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for (some of) question/editlib.php.&lt;br /&gt;
 *&lt;br /&gt;
 * @copyright &amp;amp;copy; 2006 The Open University&lt;br /&gt;
 * @author T.J.Hunt@open.ac.uk&lt;br /&gt;
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License&lt;br /&gt;
 * @package question&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/** */&lt;br /&gt;
require_once(dirname(__FILE__) . &#039;/../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
global $CFG;&lt;br /&gt;
require_once($CFG-&amp;gt;libdir . &#039;/simpletestlib.php&#039;); // Include the test libraries&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot . &#039;/question/editlib.php&#039;); // Include the code to test&lt;br /&gt;
&lt;br /&gt;
/** This class contains the test cases for the functions in editlib.php. */&lt;br /&gt;
class question_editlib_test extends UnitTestCase {&lt;br /&gt;
    function test_get_default_question_category() {&lt;br /&gt;
        // Do the test here/&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is, you have a class called something_test, and in that class you have lots of methods called test_something. Normally, you have one test method for each function you want to test, and you may as well called the test method &#039;&#039;&#039;test_name_of_function_being_tested&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Inside a test function ===&lt;br /&gt;
&lt;br /&gt;
The inside of a test function tyically looks like this: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function test_get_default_question_category() {&lt;br /&gt;
    // Set things up in preparation for the test.&lt;br /&gt;
&lt;br /&gt;
    // Call the function you want to test.&lt;br /&gt;
&lt;br /&gt;
    // Check that the result is what you expected.&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
=== Test data ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
=== setUp and tearDown methods ===&lt;br /&gt;
&lt;br /&gt;
If all your test cases relate to the same area of code, and so need the same set of test data, then you can create a method called &amp;lt;code&amp;gt;setUp()&amp;lt;/code&amp;gt; that sets up the test data. If present, this method will be called before each test method. You can write a matching &amp;lt;code&amp;gt;tearDown()&amp;lt;/code&amp;gt; method if there is any clean-up that needs to be done after each test case has run.&lt;br /&gt;
&lt;br /&gt;
If you have some test test cases the need one sort of setup, and some other test cases that need a different setup, consider splitting your tests into two separate classes, each with its own &amp;lt;code&amp;gt;setUp()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Further information ===&lt;br /&gt;
&lt;br /&gt;
The simpletest documentation is at: http://simpletest.sourceforge.net/.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changes to your existing code to make it work with unit testing ==&lt;br /&gt;
&lt;br /&gt;
When code is being tested, it gets included from inside one of the simpletest library function. If the code is expecting to be run directly (for example, if it is a view.php or index.php function), you are likely to get errors because that expectation is no longer true.&lt;br /&gt;
&lt;br /&gt;
=== Include paths ===&lt;br /&gt;
&lt;br /&gt;
Includes like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;require_once(&#039;../../config.php&#039;); // Won&#039;t work.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
won&#039;t work. Instead, the more robust option is &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;require_once(dirname(__FILE__) . &#039;/../../config.php&#039;); // Do this.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access to global variables ===&lt;br /&gt;
&lt;br /&gt;
Because your code was included from within a function, you can&#039;t access global variables until you have done a global statement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;require_once(dirname(__FILE__) . &#039;/../../config.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;libdir . &#039;/moodlelib.php&#039;); // Won&#039;t work.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;require_once(dirname(__FILE__) . &#039;/../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
global $CFG; // You need this.&lt;br /&gt;
require_once($CFG-&amp;gt;libdir . &#039;/moodlelib.php&#039;); // Will work now.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== More about unit testing in general ==&lt;br /&gt;
&lt;br /&gt;
The best book I know about unit testing is &#039;&#039;&#039;Pragmatic Unit Testing in Java with JUnit&#039;&#039; by Andrew Hunt (no relation) and David Thomas. I know, this book is not called Pragmatic Unit Testing in PHP with SimpleTest. However, it is an excellent book - short, to the point, and very practical. Most of what it says is not specific to Java and JUnit and it is obvious how to apply it in our testing setup.&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit tests]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Roadmap&amp;diff=26176</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Roadmap&amp;diff=26176"/>
		<updated>2007-05-02T23:09:40Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* Version 1.9 - Expected June 2007 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This roadmap collects the best information about upcoming features in Moodle.   It is not 100% certain - features may change according to available funding and developers.&lt;br /&gt;
&lt;br /&gt;
== Version 1.9 - Expected June 2007 ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Grades|Gradebook development]] - Moodle.com and OU&lt;br /&gt;
::The gradebook system will be revamped for performance, switching from our older &amp;quot;pull&amp;quot; model to a &amp;quot;push&amp;quot; model where all modules will now publish grades as necessary into a central table.  Support for (local/state) [[Development:Outcomes|outcomes/goals/competencies]] is included! =&amp;gt; really hope to consider including Gradebook Plus or add similar features to allow instructors to input grades directly!&lt;br /&gt;
* [[Development:Events|Event API]] - Moodle.com&lt;br /&gt;
::The new Events API provides a way for any code to &amp;quot;hook&amp;quot; into events in a clean, loosely coupled way.  it&#039;s a foundation of the new Gradebook.&lt;br /&gt;
* [[Repository API]] ? - Open University, Moodle.com, Humboldt and Warp Networks&lt;br /&gt;
::Abstract all file operations to an API that allows plugins for different external repositories&lt;br /&gt;
* [[Development:Plan_to_Improve_Flexibility_of_Question_Category_Sharing_and_Permissions|Improved question bank]] - Jamie Pratt&lt;br /&gt;
::Allows questions to be shared by the whole site, a course category, a singe course, or be kept private to a single module. More control over who can do what to each question.&lt;br /&gt;
* [[Learning Design export]]? - Moodle.com and Open University of The Netherlands&lt;br /&gt;
::We plan to have a very simple export for any Moodle course into IMS LD format, as a proof of concept and to help the community start learning about IMS LD.&lt;br /&gt;
* [[Development:Groups_documentation_for_module_developers|New groups]] - Open University&lt;br /&gt;
::Site-wide groups, reusable groups, and assigning activities to groups are the major improvements being developed  &lt;br /&gt;
* SCORM 2004?&lt;br /&gt;
* Integrate [[Dfwiki|nwiki]]?&lt;br /&gt;
* [[Development:Feedback|Integrate Feedback module]]?&lt;br /&gt;
&lt;br /&gt;
== Version 2.0 - Expected Late 2007 ==&lt;br /&gt;
&lt;br /&gt;
* [[IMS Learning Design]] - Moodle.com&lt;br /&gt;
::Support for importing/exporting LD, converting Moodle activities and sequences of activities into a standard format for sharing, and importing standard sequences into Moodle courses&lt;br /&gt;
* [[Conditional activities]] - Moodle.com&lt;br /&gt;
::Allowing dependencies and forced paths through the content&lt;br /&gt;
* [[Community hub]] interfaces - Moodle.com and others&lt;br /&gt;
::Makes it easy for users to find and navigate other systems and external Moodle repositories, leveraging the Moodle Network in various ways.&lt;br /&gt;
* [[Student Information API]]&lt;br /&gt;
::API for integrating external systems for managing student information&lt;br /&gt;
* Old DB install/upgrade system removed&lt;br /&gt;
:: The deprecated system for installing or upgrading database entries used in Moodle &amp;lt; 1.7 will be completely removed, while supporting only the new XML based database scheme introduced in 1.7&lt;br /&gt;
* [[Development:Voice|Moodle Voice]]&lt;br /&gt;
:: Moodle Voice is a project for embedding VoiceXML support into Moodle Core.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: Moodle 2.0 will require PHP 5.1 as a minimum, because of certain improvements not available in PHP 4.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Version 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* [[Development:Portfolio API]]&lt;br /&gt;
::Interface Moodle activities and repositories to help produce portfolios for internal assessment AND external publication&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;br /&gt;
[[Category:Future]]&lt;br /&gt;
&lt;br /&gt;
[[es:Planificación]]&lt;br /&gt;
[[fr:Planification]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_documentation&amp;diff=513</id>
		<title>Developer documentation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_documentation&amp;diff=513"/>
		<updated>2007-01-29T23:39:48Z</updated>

		<summary type="html">&lt;p&gt;Chuang: /* Guidelines */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039; New developer documentation pages should be added to the &#039;&#039;Development namespace&#039;&#039; by typing &amp;lt;code&amp;gt;Development:&amp;lt;/code&amp;gt; before the new page name i.e. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[New page name]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;If you are a developer, you probably want to change your [[Special:Preferences|preferences]] to include the Development namespace in searches.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Guidelines==&lt;br /&gt;
The following guidelines are crucial reading for anyone wanting to contribute to the Moodle code base:&lt;br /&gt;
*[[Coding|Coding guidelines]] have to be followed by all Moodle developers&lt;br /&gt;
*[[Moodle design goals]] spells out the basic design goals behind Moodle&lt;br /&gt;
*[[Interface guidelines]] aim to provide a common feel to the Moodle user interface&lt;br /&gt;
*[[CVS (developer)|Moodle CVS for developers]] explains how to work with the Moodle code in CVS&lt;br /&gt;
*[[Unit tests]] explains how to run the unit tests, and how to write new test cases.&lt;br /&gt;
*[[Tracker]] explains the Moodle Tracker for keeping track of bugs, issues, feature requests etc&lt;br /&gt;
*[[Working with the Community|Working with the Community]] explains how to engage with the dev community and discuss changes&lt;br /&gt;
&lt;br /&gt;
== Resources and tools ==&lt;br /&gt;
&lt;br /&gt;
*[[Developer FAQ]] - frequently asked questions, especially useful for newcomers to Moodle&lt;br /&gt;
*[http://tracker.moodle.org/ Moodle tracker] - bug reports, feature requests and other tracked issues&lt;br /&gt;
*[http://moodle.org/mod/forum/view.php?id=55 General developer forum]&lt;br /&gt;
*[http://moodle.cvs.sourceforge.net/moodle/moodle/ CVS code] - browse the Moodle code via the web&lt;br /&gt;
*[http://moodle.org/xref/nav.html?index.html Cross reference] - phpxref output for browsing Moodle source code&lt;br /&gt;
*[http://phpdocs.moodle.org/ Moodle PHP doc reference] - automatically generated documentation&lt;br /&gt;
*[[Database Schema|Database Schema]] - for recent releases&lt;br /&gt;
*[http://moodle.org/course/view.php?id=5#4 Development news and discussion] section of Using Moodle course&lt;br /&gt;
*[http://developer.yahoo.com/yui YUI documentation] - YUI is the official AJAX library in moodle.&lt;br /&gt;
*[[Setting up Eclipse for Moodle development]] - Eclipse is a great editor to use for php development, if you can work out how to set it up.&lt;br /&gt;
*[[Unmerged files]] - changes on the stable branch in CVS that have not been merged to HEAD&lt;br /&gt;
&lt;br /&gt;
==How you can contribute==&lt;br /&gt;
&lt;br /&gt;
The M in Moodle stands for &#039;Modular&#039;. There are many different types of components that you can contribute that can be plugged into Moodle to provide additional functionality. When you have developed a new component please publish it in the [http://moodle.org/mod/data/view.php?id=6009 database of Moodle modules and plugins]. The following types of plugins currently exist (in alphabetical order):&lt;br /&gt;
*[[Modules (developer)|Activity modules]]&lt;br /&gt;
*[[Admin reports|Admin reports]]&lt;br /&gt;
*[[Assignment types]]&lt;br /&gt;
*[[Authentication|Authentication methods]]&lt;br /&gt;
*[[Blocks|Blocks]]&lt;br /&gt;
*[[Course formats]]&lt;br /&gt;
*[[Database fields (developer)|Database fields]]&lt;br /&gt;
*[[Database presets]]&lt;br /&gt;
*[[Enrolment plugins (developer)|Enrolment plugins]]&lt;br /&gt;
*[[Filters|Filters]]&lt;br /&gt;
*[[Question_engine]]&lt;br /&gt;
*[[Question import/export formats]]&lt;br /&gt;
*[[Question bank|Question bank teacher docs]]&lt;br /&gt;
*[[Question_engine#Question_types|Question types developper docs]]&lt;br /&gt;
*[[Quiz reports]]&lt;br /&gt;
*[[Resource types]]&lt;br /&gt;
*[[SSO plugins]]&lt;br /&gt;
&lt;br /&gt;
There are also ways you can contribute that don&#039;t involve PHP programming:&lt;br /&gt;
*[[Themes]]&lt;br /&gt;
*[[Translation]]&lt;br /&gt;
*[[Database Schemas|Database schemas]]&lt;br /&gt;
&lt;br /&gt;
You can also help a lot by&lt;br /&gt;
*[[Tests|Testing]]&lt;br /&gt;
*[[Tracker|Participating in the bug tracker]]&lt;br /&gt;
&lt;br /&gt;
==Plans for the future==&lt;br /&gt;
Ideas for and details of planned future features of Moodle are initially discussed on the forums in the [http://moodle.org/course/view.php?id=5 Using Moodle] course at moodle.org. That developer discussions are intermixed with user discussions in the same forums may seem strange at first but is one of the reasons for the success of Moodle. It is important that both end-users and developers discuss the future features together.&lt;br /&gt;
&lt;br /&gt;
Once ideas begin to crystalize on the forums they can be summarized in this wiki, either as part of the [[Roadmap]] or in the form of [[Developer notes]]. These pages then form the basis for further discussion in the forums.&lt;br /&gt;
*[[Roadmap]]&lt;br /&gt;
*[[Developer notes]]&lt;br /&gt;
*[[Student projects]]&lt;br /&gt;
*[[Developer conference|Developer conferences]]&lt;br /&gt;
&lt;br /&gt;
==Documentation for core components==&lt;br /&gt;
This section is for documentation of specific components of the existing core Moodle code. Discussion of components that are under discussion or in development can be found in the [[Developer notes]] or on the [[Roadmap]].&lt;br /&gt;
&lt;br /&gt;
*[[Migration to Role-driven model|Migration to Role-driven model]] @ v[[1.7]]&lt;br /&gt;
*[[UTF-8 migration|Migration to UTF-8]] @ v[[:Category:Moodle 1.6|1.6]]&lt;br /&gt;
*[[Question engine]]&lt;br /&gt;
*[[Quiz developer docs|Quiz module]]&lt;br /&gt;
*[[SCORM schema|SCORM module 1.5 schema]]&lt;br /&gt;
*[[Authentication API]]&lt;br /&gt;
*[[Stats package]]&lt;br /&gt;
*[[Email processing]]&lt;br /&gt;
*[[Cookieless Sessions]]&lt;br /&gt;
*[[lib/formslib.php|Formslib]] for quickly writing code to display and process more accessible and secure forms.&lt;br /&gt;
*[[Moodle Network|Moodle Network]]&lt;br /&gt;
&lt;br /&gt;
==Documentation for contributed code==&lt;br /&gt;
Many Moodle users contribute code for the benefit of other Moodle users. This can take the form of new activity modules, blocks, themes, resource plug-ins, assignment plug-ins, question type plug-ins, question import/export formats, quiz report plug-ins, course formats, ... This code is initially posted on the forums in the [http://moodle.org/course/view.php?id=5 Using Moodle] course and then often go into the [http://cvs.sourceforge.net/viewcvs.py/moodle/contrib/ contrib area] of the Moodle [[CVS]] repository. When you have developed a new component please publish it in the [http://moodle.org/mod/data/view.php?id=6009 database of Moodle modules and plugins]. Developer documentation for these components should be listed here.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
*[http://security.moodle.org/ Moodle Security Centre]&lt;br /&gt;
*[http://moodle.com/partners/ Moodle Partners] - providers of custom Moodle development services&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[es:Documentación para Desarrolladores]]&lt;br /&gt;
[[fr:Documentation développeur]]&lt;br /&gt;
[[zh:开发者文档]]&lt;br /&gt;
[[ja:開発者ドキュメント]]&lt;/div&gt;</summary>
		<author><name>Chuang</name></author>
	</entry>
</feed>