<?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=Afhole</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=Afhole"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Afhole"/>
	<updated>2026-04-25T23:40:55Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Big_Select_List&amp;diff=39911</id>
		<title>Big Select List</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Big_Select_List&amp;diff=39911"/>
		<updated>2013-05-21T10:04:52Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ Moodle User Interface Guidelines|Moodle User Interface Guidelines]] &amp;gt; &#039;&#039;&#039;Big Select List&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Problem ==&lt;br /&gt;
User needs to select one or more items from a potentially &#039;&#039;&#039;very&#039;&#039;&#039; large master list.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Forces: factors that affect selection ==&lt;br /&gt;
&lt;br /&gt;
* If there are too many items in a list from which a user has to find items to select, finding what they need becomes difficult&lt;br /&gt;
** The largest Moodle sites have hundreds of thousands of users, tens of thousands of courses, and some courses contain over a thousand students. &lt;br /&gt;
* If there is a list with radio buttons it can be searched with the browser&#039;s find functionality, if the user knows it&lt;br /&gt;
* The SELECT element in HTML can have multiple items in it selected by pushing an additional key on the keyboard while clicking with the mouse&lt;br /&gt;
** requires quite intricate hand coordination which is probably too much for some of our users &lt;br /&gt;
** the selection is easily lost by accident &lt;br /&gt;
** users might not know about the additional key&lt;br /&gt;
* A list with too many elements on it is very slow to load&lt;br /&gt;
* A complete list of all options becomes awkward to work with before it reaches 100 entries, even if it is sorted alphabetically.&lt;br /&gt;
* If interaction with the list (adding selection, searching) requires a new page load, it easily becomes very slow and it becomes less apparent what the application did in reaction to the user&#039;s action&lt;br /&gt;
* Some users may not have javascript support on, so it cannot be depended on&lt;br /&gt;
&lt;br /&gt;
== Solution ==&lt;br /&gt;
* Put two select boxes side by side and buttons for adding and removing elements between them.&lt;br /&gt;
* Under each select box, add a text field and a &#039;Search&#039; button next to it. (In Moodle 1.9, only under the select box on the right)&lt;br /&gt;
&lt;br /&gt;
Users can select one or more elements in one of the select lists, and press &amp;lt;nowiki&amp;gt;[◀ Add]&amp;lt;/nowiki&amp;gt; or &amp;lt;nowiki&amp;gt;[Remove ▶]&amp;lt;/nowiki&amp;gt; to move them to the other list.&lt;br /&gt;
&lt;br /&gt;
Users can write a search term (which fields of the user&#039;s profile does this search?) and trigger the &amp;lt;nowiki&amp;gt;[Search]&amp;lt;/nowiki&amp;gt; to have the list only show those users with data matching the search terms. This is the only way to use the UI in case there are too many users in the list and they can not be listed all at once.&lt;br /&gt;
&lt;br /&gt;
== Examples and implementation ==&lt;br /&gt;
TODO: Further explain the example below.&lt;br /&gt;
=== Assign course roles UI ===&lt;br /&gt;
[[Image:bigselectlist-assignroles-moodle2.png|thumb|Image 1: Big Select List (Moodle 2.0)]]&lt;br /&gt;
[[Image:bigselectlist-assignroles.png|thumb|Image 2: Moodle 1.9 version of Big Select List with lots of selectable users]]&lt;br /&gt;
*Assign role &#039;x&#039; in Course: y&lt;br /&gt;
** [http://cvs.moodle.org/moodle/admin/roles/assign.php?revision=1.98&amp;amp;view=markup /moodle2cvs/admin/roles/assign.php]&lt;br /&gt;
&lt;br /&gt;
TODO: Create [[Big Select List Implementation]]&lt;br /&gt;
&lt;br /&gt;
=== Bulk User actions ===&lt;br /&gt;
See http://moodle.org/mod/forum/discuss.php?d=126884#p565022&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Another data point for the &amp;quot;Big Select List&amp;quot;: the bulk user actions page has a similar but different interface. The positions of the &amp;quot;selected&amp;quot; and &amp;quot;available&amp;quot; users are swapped, the &amp;quot;filter&amp;quot; (rather than search) box is at the very top, and the add/remove buttons are below the lists, rather than between the lists. &amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Groups: Add/remove users ===&lt;br /&gt;
An extended variation which also shows which groups a given user is in already.&lt;br /&gt;
&lt;br /&gt;
== Further information / Sources  ==&lt;br /&gt;
TODO: Anyone, if you know of any, please add references if you know any other place this kind of an UI is discussed or described. Was it created originally for Moodle?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Moodle User Interface Guidelines]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=39757</id>
		<title>Git for developers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=39757"/>
		<updated>2013-05-16T14:10:39Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Installing Git on your computer */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is for helping you get started on Moodle development with Git. For further details of Git, see [[:Category:Git]].&lt;br /&gt;
&lt;br /&gt;
== General workflow ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A reasonable knowledge of the Git basics is a good idea before you start to use it for development. If you are new to Git, you are encouraged to go to &#039;See also&#039; for some more general reading.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[image:git-pushpull-model.png|right|thumb|400px|Moodle development workflow with Git]]&lt;br /&gt;
In short, the Moodle development with Git looks like this:&lt;br /&gt;
&lt;br /&gt;
* You as the contributor commit changes into your personal repository at your computer&lt;br /&gt;
* You push the changes into your public repository and publish links to your changes in the Moodle Tracker&lt;br /&gt;
* You may ask for a peer review of your code from another developer (preferred but optional)&lt;br /&gt;
* When you are confident of your code you should submit it for integration (Integration request, also sometimes known as a pull request)&lt;br /&gt;
* Moodle integrators pull the changes from your public repository and if they like them, they put them into Moodle integration repository&lt;br /&gt;
* The integrated change is tested and finally pushed into Moodle production repository&lt;br /&gt;
* You update your local repository with all changes from the production repository and the next cycle may start again&lt;br /&gt;
&lt;br /&gt;
This workflow runs in roughly weekly cycles. The integration happens on Monday and the testing on Tuesday. On Wednesday, the production repository moodle.git is usually updated with changes from the last development week.&lt;br /&gt;
&lt;br /&gt;
Most Moodle developers have their public repositories hosted at [http://github.com/ Github]. Alternatively you may want to try [http://gitorious.org Gitorious] or the legendary [http://repo.or.cz repo.or.cz]. In the examples in this guide we assume you&#039;ll set up your public repository at Github.&lt;br /&gt;
&lt;br /&gt;
If you&#039;d like to be added to the developers group in the tracker (which allows you to assign issues to yourself), please send an email to michaeld@moodle.com with your tracker username and a link to an issue where you have contributed a patch.&lt;br /&gt;
&lt;br /&gt;
== Installing Git on your computer ==&lt;br /&gt;
&lt;br /&gt;
Install Git on your computer. Most Linux distributions have Git available as a package to install. If you are on Mac, [http://code.google.com/p/git-osx-installer/ git-osx-installer] installs it in a few clicks.&lt;br /&gt;
&lt;br /&gt;
Immediately after the installation, set your name and contact e-mail. The name and e-mail will become part of your commits and they can&#039;t be changed later once your commits are accepted into the Moodle code. Therefore we ask contributors to use their real names written in capital letters, eg &amp;quot;John Smith&amp;quot; and not &amp;quot;john smith&amp;quot; or even &amp;quot;john5677&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
    git config --global user.name &amp;quot;Your Name&amp;quot;&lt;br /&gt;
    git config --global user.email yourmail@domain.tld&lt;br /&gt;
&lt;br /&gt;
Unless you are the repository maintainer, it is wise to set your Git to not push changes in file permissions:&lt;br /&gt;
&lt;br /&gt;
    git config --global core.filemode false&lt;br /&gt;
&lt;br /&gt;
== Setting-up the public repository ==&lt;br /&gt;
&lt;br /&gt;
1. Go to [http://github.com/ Github] and create an account.&lt;br /&gt;
&lt;br /&gt;
2. Go to the [http://github.com/moodle/moodle official Moodle Github repository] and click on the Fork button. You now have your own Github Moodle repository.&lt;br /&gt;
&lt;br /&gt;
3. Now you need to set up your SSH public key, so you can push to your Github Moodle repository from your local Moodle repository. On Mac you can go on this [http://help.github.com/mac-key-setup/ Github help page]. If you are on another system, go to your Github administration page, to the section SSH Public Keys, and you should see a link to a help page. Done? Good! That was the most difficult part!&lt;br /&gt;
&lt;br /&gt;
== Setting-up the local repository at your computer  ==&lt;br /&gt;
&lt;br /&gt;
Create a local clone repository of your Github repository. In a terminal:&lt;br /&gt;
&lt;br /&gt;
    git clone git://github.com/YOUR_GITHUB_USERNAME/moodle.git LOCALDIR&lt;br /&gt;
&lt;br /&gt;
    (or:  git clone git@github.com:YOUR_GITHUB_USERNAME/moodle.git LOCALDIR)&lt;br /&gt;
&lt;br /&gt;
This command does several jobs for you. It creates a new folder, initializes an empty Git repository in it, sets your Github repository as the remote repository called &#039;origin&#039; and makes a local checkout of the branch &#039;master&#039; from it. The important point to remember now is that your Github repository is aliased as &#039;origin&#039; for your local clone.&lt;br /&gt;
&lt;br /&gt;
Note that the format of the URL here is important. In the first example, the URL starts &amp;quot;git://github.com&amp;quot; and this will give read-only access to the repository at github.com. If you use this URL, the &amp;quot;git push origin&amp;quot; command that appears later in this document will not work. Therefore, if you want to be able to update the &amp;quot;origin&amp;quot; repository, you should use the URL that starts &amp;quot;git@github.com&amp;quot;, i.e. the second of the two &amp;quot;git clone&amp;quot; commands given above. This will give you read and write access to the repository on github.com.&lt;br /&gt;
&lt;br /&gt;
== Keeping your public repository up-to-date ==&lt;br /&gt;
&lt;br /&gt;
[[image:git-sync-github.png|right|thumb|400px|Fetching changes from upstream and pushing them to github]]&lt;br /&gt;
Your fork at Github is not updated automatically. To keep it synced with the upstream Moodle repository, you have to fetch the recent changes from the official moodle.git and push them to your public repository. To avoid problems with this it is strongly recommended that you never modify the standard Moodle branches. &#039;&#039;Remember: never commit directly into master and MOODLE_xx_STABLE branches.&#039;&#039; In other words, always create topic branches to work on. In Gitspeak, the master branch and MOODLE_xx_STABLE branches should be always fast-forwardable.&lt;br /&gt;
&lt;br /&gt;
To keep your public repository up-to-date, we will register remote repository git://git.moodle.org/moodle.git under &#039;upstream&#039; alias. Then we create a script to be run regularly that fetches changes from the upstream repository and pushes them to your public repository. Note that this procedure will not affect your local working directory.&lt;br /&gt;
&lt;br /&gt;
To register the upstream remote:&lt;br /&gt;
&lt;br /&gt;
    cd moodle&lt;br /&gt;
    git remote add upstream git://git.moodle.org/moodle.git&lt;br /&gt;
&lt;br /&gt;
The following commands can be used to keep the standard Moodle branches at your Github repository synced with the upstream repository. You may wish to store them in a script so that you can run it every week after the upstream repository is updated.&lt;br /&gt;
&lt;br /&gt;
    #!/bin/sh&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    for BRANCH in MOODLE_19_STABLE MOODLE_20_STABLE MOODLE_21_STABLE MOODLE_22_STABLE MOODLE_23_STABLE MOODLE_24_STABLE master; do&lt;br /&gt;
        git push origin refs/remotes/upstream/$BRANCH:$BRANCH&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The git-fetch command does not modify your current working dir (your checkout). It just downloads all recent changes from a remote repository and stores them into so called remote-tracking branches. The git-push command takes these remote-tracking branches from upstream and pushes them to Github under the same name. Understanding this fully requires a bit knowledge of Git internals - see gitrevisions(7) man page.&lt;br /&gt;
&lt;br /&gt;
Note there is no need to switch the local branch during this. You can even execute this via cron at your machine. Just note that the upstream repository updates typically just once a week.&lt;br /&gt;
&lt;br /&gt;
=== New branches ===&lt;br /&gt;
&lt;br /&gt;
Occasionally, moodle.org will create a new branch that does not exist in your public (e.g. Github.com) repository. If you try to push this new branch, you will see an error such as the following:&lt;br /&gt;
&lt;br /&gt;
    error: unable to push to unqualified destination: MOODLE_99_STABLE&lt;br /&gt;
    The destination refspec neither matches an existing ref on the remote&lt;br /&gt;
    nor begins with refs/, and we are unable to guess a prefix based on the source ref.&lt;br /&gt;
    error: failed to push some refs to &#039;git@github.com:YOUR_GITHUB_USERNAME/moodle.git&#039;&lt;br /&gt;
&lt;br /&gt;
In the above example, &amp;quot;MOODLE_99_STABLE&amp;quot;, is the name of the new branch that does not exist in your public repository. To fix the error, you need to create the new branch on your public repository, using the following commands, replacing &amp;quot;MOODLE_99_STABLE&amp;quot; with the name of the new branch you wish to create:&lt;br /&gt;
&lt;br /&gt;
    git checkout MOODLE_99_STABLE&lt;br /&gt;
    git push origin MOODLE_99_STABLE:MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
The above code will create a new copy of the &amp;quot;MOODLE_99_STABLE&amp;quot; branch in your local repository. If you do not need to keep a local copy of the new branch - and probably you do not need it, you then can remove it from your local repository as follows:&lt;br /&gt;
&lt;br /&gt;
    git checkout master&lt;br /&gt;
    git branch -D MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
== Preparing a patch ==&lt;br /&gt;
&lt;br /&gt;
As said earlier at this page, you never work on standard Moodle branches directly. Every time you are going to edit something, switch to a local branch. Fork the local branch off the standard branch you think it should be merged to. So if you are working on a patch for 1.9 or 2.0, fork the branch off MOODLE_19_STABLE or MOODLE_20_STABLE, respectively. Patches for the next [[Moodle versions|major version]] should be based on the master branch.&lt;br /&gt;
&lt;br /&gt;
    git checkout -b MDL-xxxxx-nasty-bug origin/master&lt;br /&gt;
&lt;br /&gt;
Note that if you forget to specify the starting point, the branch is based on the currently checked-out branch. It may not be what you want. It is recommended to always specify the starting point.&lt;br /&gt;
&lt;br /&gt;
To check the current branch, run&lt;br /&gt;
&lt;br /&gt;
    git branch&lt;br /&gt;
&lt;br /&gt;
The current branch is highlighted.&lt;br /&gt;
&lt;br /&gt;
Now go and fix the issue with your favorite IDE. Check the status of the files, view the change to be committed and finally commit the change:&lt;br /&gt;
&lt;br /&gt;
    vim filename.php&lt;br /&gt;
    git status&lt;br /&gt;
    git diff&lt;br /&gt;
    git commit -a&lt;br /&gt;
&lt;br /&gt;
Note that this is safe as the commit is recorded just locally, nothing is sent to any server yet (as it would in CVS). To see history of the commits, use&lt;br /&gt;
&lt;br /&gt;
    git log&lt;br /&gt;
&lt;br /&gt;
Once your local branch contains the change (note that it may consists of several patches) and you are happy with it, publish the branch at your public repository:&lt;br /&gt;
&lt;br /&gt;
    git push MDL-xxxxx-nasty-bug&lt;br /&gt;
&lt;br /&gt;
Because we did not specify explicit remote repository, the &#039;origin&#039; is used. Because we did not specify the branch to push, the Git will use the current branch and push it to the remote repository under the same name (by default, this is a subject of your configuration. See push.default config variable).&lt;br /&gt;
&lt;br /&gt;
Now as your branch is published, you can ask Moodle core developers to review it and eventually integrate it into the standard Moodle repository.&lt;br /&gt;
&lt;br /&gt;
=== Checking if a branch has already been merged ===&lt;br /&gt;
&lt;br /&gt;
After some time contributing to Moodle you would have a lot of branches both in your local repository and in your public repository. To prune their list and delete those that were accepted by upstream, use the following&lt;br /&gt;
&lt;br /&gt;
    git fetch upstream                                      (1)&lt;br /&gt;
    git branch --merged upstream/master                     (2)&lt;br /&gt;
    git branch --merged upstream/MOODLE_20_STABLE           (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) fetches the changes from your upstream repository at git.moodle.org (remember that git-fetch does not modify your working dir so it is safe to run it whenever). Command (2) and (3) print all branches that are merged into the upstream master branch and MOODLE_20_STABLE branch, respectively. To delete these local branches, use&lt;br /&gt;
&lt;br /&gt;
    git branch -d MDL-xxxxx-accepted-branch&lt;br /&gt;
&lt;br /&gt;
The similar approach can be used to check the branches published at your origin repository at github.com&lt;br /&gt;
&lt;br /&gt;
    git fetch origin                                        (1)&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    git branch -r --merged upstream/master                  (2)&lt;br /&gt;
    git branch -r --merged upstream/MOODLE_20_STABLE        (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) makes sure that you have all your branches from github.com recorded as the remote tracking branch locally. Commands (2) and (3) work the same as in the previous example but they list remote tracking branches only ([http://www.kernel.org/pub/software/scm/git/docs/git-branch.html see -r param]). To delete a branch at github.com, use&lt;br /&gt;
&lt;br /&gt;
    git push origin :MDL-xxxx-branch-to-delete&lt;br /&gt;
&lt;br /&gt;
This syntax may look weird to you. However it is pretty logical. The general syntax of the git-push command is&lt;br /&gt;
&lt;br /&gt;
    git push &amp;lt;repository&amp;gt; &amp;lt;source ref&amp;gt;:&amp;lt;target ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
so deleting a remote branch can be understood as pushing an &amp;quot;empty (null) reference&amp;quot; to it.&lt;br /&gt;
&lt;br /&gt;
== Peer-reviewing someone else&#039;s code ==&lt;br /&gt;
&lt;br /&gt;
To review a branch that someone else pushed into their public repository, you do not need to register a new remote (unless you work with such repository frequently, of course). Let us imagine your friend Alice pushed a work-in-progress branch called &#039;wip-feature&#039; into her Github repository and asked you to review it. You need to know the read-only address of the repository and the name of the branch.&lt;br /&gt;
&lt;br /&gt;
    git fetch git://github.com/alice/moodle.git wip-feature&lt;br /&gt;
&lt;br /&gt;
This will download all required data and will keep the pointer to the tip of the wip-feature branch in a local symbolic reference FETCH_HEAD. To see what&#039;s there on that branch, use&lt;br /&gt;
&lt;br /&gt;
    git log -p FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see how a particular file looks at Alice&#039;s branch&lt;br /&gt;
&lt;br /&gt;
    git show FETCH_HEAD:admin/blocks.php&lt;br /&gt;
&lt;br /&gt;
To create a new local branch called &#039;alice-wip-feature&#039; containing the work by Alice, use&lt;br /&gt;
&lt;br /&gt;
    git checkout -b alice-wip-feature FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To merge Alice&#039;s work into your current branch:&lt;br /&gt;
&lt;br /&gt;
    git merge FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see what would be merged into the current branch without actually modifying anything:&lt;br /&gt;
&lt;br /&gt;
    git diff ...FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
Once you are all set and reviewing code, this [[Peer_reviewing_checklist|checklist]] should prove to be useful.&lt;br /&gt;
&lt;br /&gt;
== Rebasing a branch ==&lt;br /&gt;
&lt;br /&gt;
Rebasing is a process when you cut off the branch from its current start point and transplant it to another point. Let us assume the following history exists:&lt;br /&gt;
&lt;br /&gt;
          A---B---C topic&lt;br /&gt;
         /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
From this point, the result of the command:&lt;br /&gt;
&lt;br /&gt;
    git rebase master topic&lt;br /&gt;
&lt;br /&gt;
would be:&lt;br /&gt;
&lt;br /&gt;
                  A&#039;--B&#039;--C&#039; topic&lt;br /&gt;
                 /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
and would end with &#039;topic&#039; being your current branch.&lt;br /&gt;
&lt;br /&gt;
You may be asked to rebase your branch submitted for the integration if the submitted branch was based on an outdated commit. The typical case is if you create a new branch as a fork off the upstream master branch on Tuesday. Then on Wednesday, the upstream master branch grows as all changes from the last integration cycle are merged to it. To make diff easy on Github for next weekly pull request review, you want to rebase your branch against the updated master.&lt;br /&gt;
&lt;br /&gt;
    git rebase master MDL-xxxxx-topic-branch&lt;br /&gt;
&lt;br /&gt;
Note that rebasing effectively rewrites the history of the branch. &#039;&#039;&#039;Do not rebase the branch if there is a chance that somebody has already forked it and based their own branch on it.&#039;&#039;&#039; For this reason, many Git tutorials discourage from rebasing any branch that has been published. However in Moodle, all branches submitted for integration are potential subject of rebase (even though we try to not to do it often) and you should not base your own branches on them.&lt;br /&gt;
&lt;br /&gt;
=== Conflicts during rebase ===&lt;br /&gt;
&lt;br /&gt;
During the rebase procedure, conflicts may appear. git-status commands reports the conflicted files. Explore them carefully and fix them in your editor (like you would do with CVS). Then add the files with &#039;git add&#039; command and continue.&lt;br /&gt;
&lt;br /&gt;
    vim conflicted.php&lt;br /&gt;
    git add conflicted.php&lt;br /&gt;
    git rebase --continue&lt;br /&gt;
&lt;br /&gt;
== Applying changes from one branch to another ==&lt;br /&gt;
&lt;br /&gt;
Most bugs are fixed at a stable branch (like MOODLE_20_STABLE) and the fix must be prepared for other branches, too (like MOODLE_21_STABLE and the main development branch - master). In Moodle, we do not merge stable branches into the master one. So usually the contributor prepares at least two branches - with the fix for the stable branch(es) and with the fix for the master branch.&lt;br /&gt;
&lt;br /&gt;
If you have a patch prepared on a local branch (let us say MDL-xxxx-topic_20_STABLE), it is possible to re-apply it to another branch.&lt;br /&gt;
&lt;br /&gt;
=== Cherry-picking a single commit ===&lt;br /&gt;
&lt;br /&gt;
Let us have two local Git repositories ~/public_html/moodle21 containing local installation of Moodle 2.1 and ~/public_html/moodledev with the local installation of most recent development version of Moodle. They both use your public repository at github.com as the origin. You have a branch in moodle21 called MDL-xxxx-topic_21_STABLE that was forked off MOODLE_21_STABLE. It contains one commit. Now you want to re-apply this commit to a branch MDL-xxxx-topic in moodledev.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master            (1)&lt;br /&gt;
    git fetch ../moodle21 MDL-xxxx-topic_21_STABLE          (2)&lt;br /&gt;
    git cherry-pick FETCH_HEAD                              (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) creates new local branch forked off the CONTHERE The command (1) fetches all data needed to re-apply the topic branch and stores the pointer to the tip of that branch to FETCH_HEAD symbolic reference. The command (2) picks the tip of the branch (the top-most commit on it) and tries to apply it on the current branch. There is also a variant of the cherry-pick command that supports multiple commits (see its man page for details) but we will use another approach for that situation.&lt;br /&gt;
&lt;br /&gt;
=== Applying a set of patches ===&lt;br /&gt;
&lt;br /&gt;
If the branch MDL-xxxx-topic_21_STABLE from the previous example consists of several commits, it may be easier to use git-format-patch and git-am combo to re-apply the whole set of patches (aka patchset). Firstly you will export all commits from the topic branch to files.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodle21&lt;br /&gt;
    mkdir .patches&lt;br /&gt;
    git format-patch -o .patches MOODLE_21_STABLE..MDL-xxxx-topic_21_STABLE         (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) takes all commits from the topic branch that are not in MOODLE_21_STABLE and exports them one by one to the output directory .patches. Look at the generated files. They contain the patch itself (in diff format) and additional information about the commit. You could eg send these files by email to a friend of yours for peer-review. We will use them in another repository.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master&lt;br /&gt;
    git am -3 ../moodle21/.patches/*                        (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) applies all the files from the .patches directory. When a patch does not apply cleanly, the command tries fall back on 3-way merge (see the -3 parameter). If conflicts occur during the procedure, you can either deal with them and then use `git am --continue` or abort the whole procedure with `git am --abort`.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
; Moodle forum discussions&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=168094 GIT help needed]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=165236 Best way to manage CONTRIB code with GIT]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167063 Handy Git tip for tracking 3rd-party modules and plugins]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167730 Moodle Git repositories]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=183409 Git help!! I don&#039;t understand rebase enough...]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=217617 add MOODLE_24_STABLE to github.com repository]&lt;br /&gt;
&lt;br /&gt;
; External resources &lt;br /&gt;
* [http://www.kernel.org/pub/software/scm/git/docs/everyday.html Everyday GIT With 20 Commands Or So]&lt;br /&gt;
* [http://gitref.org/ Git Reference]&lt;br /&gt;
* [http://progit.org/book/ Pro Git book]&lt;br /&gt;
* [http://blip.tv/scott-chacon/git-talk-4113729 Getting git by Scott Chacon] - an recording of an excellent 1-hour presentation that introducing git, including a simple introduction to what is going on under the hood.&lt;br /&gt;
&lt;br /&gt;
[[Category:Git]]&lt;br /&gt;
&lt;br /&gt;
[[ja:開発者用Git]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=39546</id>
		<title>Behat integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Behat_integration&amp;diff=39546"/>
		<updated>2013-05-08T10:43:33Z</updated>

		<summary type="html">&lt;p&gt;Afhole: Possessive pronoun pedantry&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the internals of Behat and the integration with Moodle. For the functional description see [[Acceptance_testing]].&lt;br /&gt;
&lt;br /&gt;
Behat is a framework for behaviour driven development (BDD) allows us to specify Moodle functionalities (aka features) as a human-readable list of steps and parse this steps to execute actions to simulate user interaction, it executes the actions against a headless browsers (without javascript support, only curl-kind petitions) or user simulation tools like Selenium, which interacts with browsers and allows Javascript events simulation.&lt;br /&gt;
&lt;br /&gt;
(This is not in standard Moodle yet: to play a bit with features files and Moodle clone you can install the proof of concept we worked on from https://github.com/moodlehq/moodle-behat-features and follow the installation and usage instructions, you may need to hack a bit to pass all the tests, it depends on you Moodle site contents. Is an example of tool usage but not an example of good practices to create tests and specify fixtures; the current work in progress is being done in http://tracker.moodle.org/browse/MDL-35611 and subtasks, you can checkout https://github.com/dmonllao/moodle/tree/MDL-36269_master this branch is always up-to-date according to this documentation page)&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
The aim of this integration is to allow Moodle components to have its own set of features and steps definitions, this allows BDD in Moodle and allows us to execute periodically the whole set of tests to detect regressions and test the Moodle features in different environments (browsers, DBs engines, web servers...). The Moodle QA tests will be progressively rewritten according to this format to run automatically.&lt;br /&gt;
&lt;br /&gt;
== How Behat works ==&lt;br /&gt;
This section aims to explain the basics about BDD and Behat and a quick view of how Behat internally works from the CLI command execution to the results output.&lt;br /&gt;
&lt;br /&gt;
Some terms used:&lt;br /&gt;
* &#039;&#039;&#039;Features&#039;&#039;&#039;: Human-readable list of scenarios that describes a feature&lt;br /&gt;
&lt;br /&gt;
  @auth&lt;br /&gt;
  &#039;&#039;&#039;Feature&#039;&#039;&#039;: Login&lt;br /&gt;
    In order to login&lt;br /&gt;
    As a moodle user&lt;br /&gt;
    I need to be able to validate the username and password against moodle&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an unexisting user&lt;br /&gt;
      Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
      When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
      And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
      And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
      Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Human-readable list of steps to describe an expected behaviour&lt;br /&gt;
  &#039;&#039;&#039;Scenario&#039;&#039;&#039;: Login as an existing user&lt;br /&gt;
    Given I am on &amp;quot;login/index.php&amp;quot;&lt;br /&gt;
    When I fill in &amp;quot;username&amp;quot; with &amp;quot;admin&amp;quot;&lt;br /&gt;
    And I fill in &amp;quot;password&amp;quot; with &amp;quot;moodle&amp;quot;&lt;br /&gt;
    And I press &amp;quot;loginbtn&amp;quot;&lt;br /&gt;
    Then I should see &amp;quot;Moodle 101: Course Name&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;Steps&#039;&#039;&#039;: Human-readable sentences that describes an action. There are 3 types of steps, &amp;quot;Given&amp;quot; describing the initial context, &amp;quot;When&amp;quot; the event that provokes a change and &amp;quot;Then&amp;quot; where the outcomes should be asserted.&lt;br /&gt;
  I click on the &amp;quot;Add user&amp;quot; button&lt;br /&gt;
* &#039;&#039;&#039;Steps definitions&#039;&#039;&#039;: PHP methods referenced by steps when matching it&#039;s regular expression. The @Given, @When and @Then tags are descriptive and they are not taken into account when matching steps with steps definitions. The regular expressions placeholders are returned to the PHP method as arguments so methods can use them to tell the browser which button (for example) they want to click.&lt;br /&gt;
  /**&lt;br /&gt;
   * @When /^I click on the &amp;quot;(.*)&amp;quot; button$/&lt;br /&gt;
   */&lt;br /&gt;
  public function i_click_on_the_button($button) {&lt;br /&gt;
    // Simulates the user interaction (see Mink description below for more info)&lt;br /&gt;
    $this-&amp;gt;getSession()-&amp;gt;getPage()-&amp;gt;pressButton($button);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
* &#039;&#039;&#039;Behat&#039;&#039;&#039;: PHP framework and CLI application that wraps the whole process of features files loading + features files parsing + execution of actions in the browser + results output (http://behat.org/)&lt;br /&gt;
* &#039;&#039;&#039;Gherkin&#039;&#039;&#039;: Human-readable language used to define features that can be parsed and translated into PHP methods. For more info, it&#039;s the same language used by Cucumber, the BDD Ruby framework (https://github.com/cucumber/cucumber/wiki/Gherkin)&lt;br /&gt;
* &#039;&#039;&#039;Context&#039;&#039;&#039;: In Behat scope a context is a PHP class that groups steps definitions (as methods)&lt;br /&gt;
* &#039;&#039;&#039;Mink&#039;&#039;&#039;: Is the component which interacts with browsers, simulating a real user interaction. It allows us to write PHP code (or use the available PHP methods) to send petitions to the different browsers APIs through a common interface or extend it to allow browser-specific actions. The supported browsers includes Selenium, Selenium2, Sahi... http://mink.behat.org/&lt;br /&gt;
* &#039;&#039;&#039;Selenium 2&#039;&#039;&#039;: Web browser automation tool, applications like Mink can communicate with it through a RESTful API (http://code.google.com/p/selenium/wiki/JsonWireProtocol) to execute actions simulating user interaction.&lt;br /&gt;
* &#039;&#039;&#039;Selector type&#039;&#039;&#039;: Related with &#039;&#039;&#039;locator&#039;&#039;&#039;, is a way to select a node inside the page DOM, more info in https://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps&lt;br /&gt;
* &#039;&#039;&#039;Locator&#039;&#039;&#039;: Is what we are looking for inside the page DOM, it completely depends on the associated selector type, a few examples of it:&lt;br /&gt;
** Selector type = &amp;quot;link&amp;quot;, Locator = &amp;quot;Link text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;field&amp;quot;, Locator = &amp;quot;Field legend text&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;css&amp;quot;, Locator = &amp;quot;.css-class #id&amp;quot;&lt;br /&gt;
** Selector type = &amp;quot;xpath&amp;quot;, Locator = &amp;quot;//input[@id=&#039;id-value&#039;]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All this components are written in PHP, open sourced and packaged in a single and extensible framework.&lt;br /&gt;
&lt;br /&gt;
=== Quick view of the whole process ===&lt;br /&gt;
&lt;br /&gt;
# Behat CLI execution&lt;br /&gt;
#* Behat application initialization and loading of arguments (features files to execute, output format...)&lt;br /&gt;
#* Reads the Behat config file (browser servers are specified here)&lt;br /&gt;
#* Extensions overrides management&lt;br /&gt;
#* Gherkin initialization&lt;br /&gt;
# Features files selection&lt;br /&gt;
#* According to the arguments Gherkin looks for .features files&lt;br /&gt;
#** It can use different features loaders (single file, a directory, the default directory...)&lt;br /&gt;
#** The framework can be extended to allow multiple folders loading&lt;br /&gt;
# Features parsing (Gherkin)&lt;br /&gt;
#* Loops through the loaded features files looking for scenarios&lt;br /&gt;
#* Gets the list of steps of each scenario&lt;br /&gt;
#* There are hooks at different levels (http://docs.behat.org/guides/3.hooks.html)&lt;br /&gt;
# Steps parsing (Gherkin)&lt;br /&gt;
#* Gherkin looks in the available steps definitions for a regular expression that matches the step text&lt;br /&gt;
# Step definition execution&lt;br /&gt;
#* The step definition code is executed&lt;br /&gt;
#* Steps definitions most of the time uses the Mink component to communicate with the browser API sending petitions like &amp;quot;click on that button&amp;quot; or &amp;quot;go to XXX page&amp;quot;&lt;br /&gt;
# Scenario outcomes&lt;br /&gt;
#* The scenario counts as failed if an exception is thrown when executing a step definition (for example trying to click a non-existing button)&lt;br /&gt;
#* The scenario counts as passed if no exception is thrown during it&#039;s steps execution&lt;br /&gt;
# Finishing CLI execution&lt;br /&gt;
#* A summary with all the scenario results is displayed&lt;br /&gt;
#* It accepts different output formats (like JUnitXML) to it&#039;s execution in continuous integration systems (http://docs.behat.org/guides/6.cli.html#format-options)&lt;br /&gt;
&lt;br /&gt;
== Moodle integration ==&lt;br /&gt;
&lt;br /&gt;
It follows the approach chosen with PHPUnit:&lt;br /&gt;
* It comes disabled by default, Behat is not included within Moodle and it has to be installed separately with the composer installer&lt;br /&gt;
* Moodle components (subsystems and plugins) can have a tests/behat/ folder&lt;br /&gt;
* The scenarios are executed in a test environment, the production database and dataroot are not affected by the tests modifications&lt;br /&gt;
* The scenarios specifies their own fixtures and it&#039;s execution is isolated from other scenarios and features, resetting the test database and the test dataroot before each scenario&lt;br /&gt;
* Moodle lists the features files and steps definitions of it&#039;s components in a behat.yml file, similar to the phpunit.xml manifest&lt;br /&gt;
* A basic behat.yml.dist config file has been included&lt;br /&gt;
&lt;br /&gt;
=== Alternative environment ===&lt;br /&gt;
Acceptance testing implies interaction with the browser like real users does, so it requires the site to be accessible via URL. The Moodle integration uses the PHP 5.4 built-in web server to run the tests in a sandbox without affecting the production environment, switching the regular $CFG-&amp;gt;wwwroot, $CFG-&amp;gt;dataroot and $CFG-&amp;gt;prefix to alternatives only accessible from localhost, info about how to run the tests in https://docs.moodle.org/dev/Acceptance_testing#Running_tests. &lt;br /&gt;
&lt;br /&gt;
This default configuration is useful when developing in a local host, but to run the tests automatically with Jenkins, travis, other CI systems or with saucelabs we provide a few extra settings; more info in https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage&lt;br /&gt;
&lt;br /&gt;
All the CLI utilities uses $CFG-&amp;gt;behat_prefix and $CFG-&amp;gt;behat_dataroot instead of the regular one, this scripts are self-contained, but as we are accessing through a browser, we also need to switch the whole Moodle instance to test mode. For this there are two requirements:&lt;br /&gt;
&lt;br /&gt;
* Test mode is enabled if&lt;br /&gt;
** &#039;&#039;&#039;php admin/tool/behat/cli/init.php&#039;&#039;&#039; or &#039;&#039;&#039;php admin/tool/behat/cli/util.php --enable&#039;&#039;&#039; has been executed&lt;br /&gt;
* Test mode is requested if&lt;br /&gt;
** The vendor/bin/behat command is running, we know it because we hook the Behat process before the tests begins to run and we require moodle config.php after it&lt;br /&gt;
** We are accessing Moodle through the PHP 5.4 built-in web server, php_sapi_name() == &#039;cli-server&#039;&lt;br /&gt;
** We are using $CFG-&amp;gt;behat_switchcompletely (https://docs.moodle.org/dev/Acceptance_testing#Advanced_usage for more info)&lt;br /&gt;
&lt;br /&gt;
With this approach we also allow the execution of the regular Moodle environment using the PHP 5.4 built-in web server for testing/dev purposes and we restrict the possibilities of a human mistake that can prevent production site&#039;s users to access their site.&lt;br /&gt;
&lt;br /&gt;
=== Javascript ===&lt;br /&gt;
There are two types of tests depending on if their scenario needs a real browser capable of execute Javascript or if they can run in a headless browser.&lt;br /&gt;
* Tests with Javascript requires interaction with a browser through a user simulation tool like Selenium or ZombieJS to be executed; see http://mink.behat.org/#different-browsers-drivers for all available drivers&lt;br /&gt;
* Test that does not requires Javascript are faster to run but can not test rich applications like Moodle&lt;br /&gt;
&lt;br /&gt;
In most of the cases a Javascript test would be more appropriate because most of the users uses Javascript-capable browsers, non-Javascript tests can be useful to ensure that Moodle maintains it&#039;s functionality without Javascript enabled and to ensure there are no big issues, regressions or exceptions in general.&lt;br /&gt;
&lt;br /&gt;
=== Admin tool &amp;quot;Acceptance testing&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
There is an admin tool to run and ease the creation of acceptance tests. &lt;br /&gt;
* Web interface: The web interface allows you to list and filter the available steps definitions, a non-technical user can use this interface to write new features (admin/tool/behat/index.php)&lt;br /&gt;
* CLI: Command to enable and disable the test environment and to update the behat.yml file with the system tests and steps definitions (admin/tool/behat/cli/util.php and admin/tool/behat/cli/init.php for a quick start)&lt;br /&gt;
&lt;br /&gt;
=== Available steps to create tests ===&lt;br /&gt;
There are libraries with tons of steps definitions to run all sort of processes and interactions with the browser, some of them overlaps Moodle-specific libraries and tests writers can be confused not only by this also by the amount of steps and vague or too technical stepsdescriptions. Moodle provides a set of steps definitions written in a common format to make tests writers life easier. New steps definitions must follow this guidelines: https://docs.moodle.org/dev/Acceptance_testing#Adding_steps_definitions&lt;br /&gt;
&lt;br /&gt;
=== Behat extension ===&lt;br /&gt;
A new Behat extension (https://github.com/moodlehq/moodle-behat-extension) has been created to maintain Behat and its dependencies as they comes from upstream.&lt;br /&gt;
&lt;br /&gt;
The aim of this extension is:&lt;br /&gt;
* Load features from multiple folders (Moodle subsystems and plugins)&lt;br /&gt;
* Load steps definitions from multiple folders and add them as subcontexts (Moodle subsystems and plugins)&lt;br /&gt;
* Return the available steps definitions in a more human-readable format without regexps&lt;br /&gt;
&lt;br /&gt;
All the other particularities of this integration can managed playing with different Behat config parameters.&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Enrolment_usage_overview&amp;diff=36124</id>
		<title>Enrolment usage overview</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Enrolment_usage_overview&amp;diff=36124"/>
		<updated>2012-11-08T10:02:22Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Enrolment usage overview&lt;br /&gt;
|state = In progress&lt;br /&gt;
|tracker = MDL-21655&lt;br /&gt;
|discussion = n/a&lt;br /&gt;
|assignee = [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
=Goals=&lt;br /&gt;
There is a lot of confusion related to guest access, enrolment of users, etc. This page is trying to sum up the usage of enrolments and guest access in various parts of Moodle.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
; enrolment : All enrolled users enrolled in a course record in user_enrolments table. The original moodle/course:view is reset during 2.0 upgrade and all data is migrated to this new enrolment table.&lt;br /&gt;
; guest user : Local user account with username &#039;&#039;guest&#039;&#039;, for performance reasons guest id is cached in $CFG, guest is never returns by get_users_by_capability() or get_enrolled_users(), all write and dangerous capabilities are blocked in has_capability().&lt;br /&gt;
; viewing/inspection : Users with moodle/course:view at course or higher level, users are not visible inside course unless they post or do other visible action.&lt;br /&gt;
; course guest access : Those are users that are not enrolled or just viewing, but still &#039;&#039;somehow&#039;&#039; get through the require_login($course), the enrolment plugins are supposed to grant this temporary guest access, usually the user is granted some guest role on the fly.&lt;br /&gt;
; administrator access : Administrators do not have any role assigned any more, instead list of administrators is stored in CFG variable. Administrators are not returned from any accesslib queries, the only function explicitly dealing with administrators is the has_capability().&lt;br /&gt;
&lt;br /&gt;
=Core API=&lt;br /&gt;
&lt;br /&gt;
; get_enrolled_users() : returns list of userids that are already enrolled (everybody on frontpage) optionally with some capability&lt;br /&gt;
; get_enrolled_sql() : return the sql select used in get_enrolled_users() &lt;br /&gt;
; isguest() : returns true for guest user account and users with temporary guest access&lt;br /&gt;
; isguestuser() : return true only for the real guest account (username==guest)&lt;br /&gt;
; is_siteadmin() : returns true for all site admins&lt;br /&gt;
; has_capability() : returns true if user has capability, if $doanything==true used returns true for all admins&lt;br /&gt;
; get_users_by_capability() : the same as in 1.9&lt;br /&gt;
; is_enrolled() : returns true if user enrolled, on frontpage true for everybody&lt;br /&gt;
; is_viewing() : returns true if user administrator or has inspect capability&lt;br /&gt;
&lt;br /&gt;
=Core usage=&lt;br /&gt;
&lt;br /&gt;
==Group membership==&lt;br /&gt;
Only enrolled users may be members of groups. In 1.9 and earlier we only guess by looking at roles that have moodle/course:view which is not hidden, this may actually return incorrect results if overrides used. All group membership is removed when un-enrolling from course.&lt;br /&gt;
&lt;br /&gt;
Technically we need to look only at users that are returned by get_enrolled_users() when looking for new group membership candidates. Existing group membership should be filtered so that only enrolled users are displayed.&lt;br /&gt;
&lt;br /&gt;
==Gradebook==&lt;br /&gt;
&lt;br /&gt;
We keep only grades of enrolled users. Gradebook shows only enrolled users that have the gradebook role. In future it could be controlled by a special capability instead, this was not possible in 1.9 for performance reasons.&lt;br /&gt;
&lt;br /&gt;
Anybody with capability may grade or manage gradebook.&lt;br /&gt;
&lt;br /&gt;
==Logs and reports==&lt;br /&gt;
In some cases we want to see only enrolled users, in others we want to see really all users. This should be decided by a new capability.&lt;br /&gt;
&lt;br /&gt;
==User profiles==&lt;br /&gt;
&lt;br /&gt;
Only enrolled user have course visible profile.&lt;br /&gt;
Users that have one of $CFG-&amp;gt;coursemanager roles have profile on site level because we want them to be clickable on course description page. (This was originally controlled by isteacherinanycourse() which was both deprecated and incorrect.)&lt;br /&gt;
&lt;br /&gt;
Profile displays also user roles in course, the list of roles is the same as on the profile page.&lt;br /&gt;
&lt;br /&gt;
==Participation page==&lt;br /&gt;
&lt;br /&gt;
Participants page displays only enrolled users (with moodle/course:participate capability).&lt;br /&gt;
It shows only limited number of roles specified in the $CFG-&amp;gt;profileroles setting.&lt;br /&gt;
&lt;br /&gt;
==Messaging==&lt;br /&gt;
&lt;br /&gt;
There is an ongoing discussion about limiting of communication to Teacher-Student only, I do not think we should restrict this - they may use modules like Consultation or Dialog instead. In any case the current 2.0dev messaging needs a lot more work both on performance and usability.&lt;br /&gt;
&lt;br /&gt;
==Comments==&lt;br /&gt;
Comments can be controlled by capability.&lt;br /&gt;
&lt;br /&gt;
==Ratings==&lt;br /&gt;
Ratings can be controlled by capability.&lt;br /&gt;
&lt;br /&gt;
=Modules=&lt;br /&gt;
&lt;br /&gt;
==Assignment==&lt;br /&gt;
&lt;br /&gt;
Only enrolled user with submit capability may submit.&lt;br /&gt;
&lt;br /&gt;
Users with capability may grade.&lt;br /&gt;
&lt;br /&gt;
==Chat==&lt;br /&gt;
&lt;br /&gt;
Users with capability may chat.&lt;br /&gt;
&lt;br /&gt;
==Choice==&lt;br /&gt;
&lt;br /&gt;
Enrolled users with capability may make a choice. In theory there could be a setting to require capability only.&lt;br /&gt;
&lt;br /&gt;
The enrolment is important especially when there is a limited number of slots or when we want to display list of users that did not make a choice yet.&lt;br /&gt;
&lt;br /&gt;
==Feedback==&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
* Enrolled users with capability only&lt;br /&gt;
* Users with capability&lt;br /&gt;
* All users including guest (non standard feature disabled by default for security reasons)&lt;br /&gt;
&lt;br /&gt;
==Forum==&lt;br /&gt;
&lt;br /&gt;
Anybody with capability may post. Enrolled users may get notifications via email or track new posts.&lt;br /&gt;
&lt;br /&gt;
==Glossary==&lt;br /&gt;
&lt;br /&gt;
Anybody with capability may post.&lt;br /&gt;
&lt;br /&gt;
==Lesson==&lt;br /&gt;
&lt;br /&gt;
Anybody with capability may try it, grades are recorded only for enrolled.&lt;br /&gt;
&lt;br /&gt;
==Quiz==&lt;br /&gt;
&lt;br /&gt;
Anybody with capability could try it. Only enrolled with capability are displayed as those that did not pass grade yet. Only grades of enrolled are passed to gradebook.&lt;br /&gt;
&lt;br /&gt;
==SCORM==&lt;br /&gt;
Anybody with capability may try it.&lt;br /&gt;
&lt;br /&gt;
==Survey==&lt;br /&gt;
Only enrolled with capability may answer it.&lt;br /&gt;
&lt;br /&gt;
==Wiki==&lt;br /&gt;
&lt;br /&gt;
Anybody with capability may edit.&lt;br /&gt;
&lt;br /&gt;
==Workshop==&lt;br /&gt;
&lt;br /&gt;
Only enrolled with capabilities may participate.&lt;br /&gt;
&lt;br /&gt;
=Blocks=&lt;br /&gt;
&lt;br /&gt;
==Online users==&lt;br /&gt;
&lt;br /&gt;
We need separate capability to see all or enrolled users.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Role archetypes]]&lt;br /&gt;
* [[New permissions evaluation in 2.0]]&lt;br /&gt;
* [[New_enrolments in 2.0]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Enrolment]]&lt;br /&gt;
[[Category:Groups]]&lt;br /&gt;
[[Category:Roles]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=35589</id>
		<title>User:Alastair Hole</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=35589"/>
		<updated>2012-09-17T14:25:07Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m currently working for University of Bath as a Senior Educational Software &amp;amp; Systems Developer&lt;br /&gt;
&lt;br /&gt;
I have also been involved in some plugin development, chiefly the [http://www.mrcute.co.uk/ MrCUTE repository]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Enrolment_plugins&amp;diff=35588</id>
		<title>Talk:Enrolment plugins</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Enrolment_plugins&amp;diff=35588"/>
		<updated>2012-09-17T14:13:32Z</updated>

		<summary type="html">&lt;p&gt;Afhole: Created page with &amp;quot;Is there any current developer documentation for 2.*? (Looking for info for 2.2 specifically) --~~~~&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Is there any current developer documentation for 2.*? (Looking for info for 2.2 specifically) --[[User:Alastair Hole|Alastair Hole]] 22:13, 17 September 2012 (WST)&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22492</id>
		<title>User:Alastair Hole</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22492"/>
		<updated>2010-08-01T17:42:07Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m a Web Developer working for [http://www.wortech.ac.uk/ Worcester College of Technology], developing and supporting the college&#039;s Moodle implementation.&lt;br /&gt;
&lt;br /&gt;
I have also been involved in some plugin development, chiefly the [http://www.mrcute.co.uk/ MrCUTE repository]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22491</id>
		<title>User:Alastair Hole</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22491"/>
		<updated>2010-08-01T17:41:26Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m a Web Developer working for Worcester College of Technology, developing and supporting the college&#039;s Moodle implementation.&lt;br /&gt;
&lt;br /&gt;
I have also been involved in some plugin development, chiefly the [http://www.mrcute.co.uk MrCUTE repository]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22490</id>
		<title>User:Alastair Hole</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22490"/>
		<updated>2010-08-01T17:41:12Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I&#039;m a Web Developer working for Worcester College of Technology, developing and supporting the college&#039;s Moodle implementation.&lt;br /&gt;
&lt;br /&gt;
I have also been involved in some plugin development, chiefly the [http://www.mrcute.co.uk MrCUTE repository MrCUTE]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22489</id>
		<title>User:Alastair Hole</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User:Alastair_Hole&amp;diff=22489"/>
		<updated>2010-08-01T17:38:46Z</updated>

		<summary type="html">&lt;p&gt;Afhole: New page: Author of MrCUTE Repository http://www.mrcute.co.uk&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Author of MrCUTE Repository http://www.mrcute.co.uk&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28053</id>
		<title>Talk:JavaScript guidelines</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28053"/>
		<updated>2010-06-13T17:47:35Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Getting Moodle to load your JavaScript files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== event handlers ==&lt;br /&gt;
Should there be a recommendation to use YUI event handlers instead of JavaScript&#039;s inline event handlers? This might be better for cross-browser compatibility. --[[User:Frank Ralf|Frank Ralf]] 09:24, 15 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:Good idea--[[User:Tim Hunt|Tim Hunt]] 03:16, 16 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Getting Moodle to load your JavaScript files ==&lt;br /&gt;
are in_head and asap now obsolete?&lt;br /&gt;
It seems in_head is replaced by the second parameter to the js class constructor, is there an alternative for asap? --[[User:Alastair Hole|Alastair Hole]] 17:46, 13 June 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28052</id>
		<title>Talk:JavaScript guidelines</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28052"/>
		<updated>2010-06-13T17:46:57Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Getting Moodle to load your JavaScript files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== event handlers ==&lt;br /&gt;
Should there be a recommendation to use YUI event handlers instead of JavaScript&#039;s inline event handlers? This might be better for cross-browser compatibility. --[[User:Frank Ralf|Frank Ralf]] 09:24, 15 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:Good idea--[[User:Tim Hunt|Tim Hunt]] 03:16, 16 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Getting Moodle to load your JavaScript files ==&lt;br /&gt;
are in_head and asap now obsolete?&lt;br /&gt;
It seems in_head is replaced by the second parameter to the js class, is there an alternative for asap? --[[User:Alastair Hole|Alastair Hole]] 17:46, 13 June 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28051</id>
		<title>Talk:JavaScript guidelines</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:JavaScript_guidelines&amp;diff=28051"/>
		<updated>2010-06-13T17:46:17Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* event handlers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== event handlers ==&lt;br /&gt;
Should there be a recommendation to use YUI event handlers instead of JavaScript&#039;s inline event handlers? This might be better for cross-browser compatibility. --[[User:Frank Ralf|Frank Ralf]] 09:24, 15 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:Good idea--[[User:Tim Hunt|Tim Hunt]] 03:16, 16 June 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Getting Moodle to load your JavaScript files ==&lt;br /&gt;
are in_head and asap now obsolete?&lt;br /&gt;
It seems in_head is replaced by the second parameter to the js class, is there an alternative for asap?&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Compiling_FreeTDS_under_Windows&amp;diff=11856</id>
		<title>Compiling FreeTDS under Windows</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Compiling_FreeTDS_under_Windows&amp;diff=11856"/>
		<updated>2009-09-17T13:40:43Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Requirements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Requirements==&lt;br /&gt;
&lt;br /&gt;
* MSVC 6.0 (Microsoft Visual C++ 6.0) with Service Packs installed.&lt;br /&gt;
* FreeTDS (tested with [http://www.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-0.82.tar.gz version 0.82] + [http://freetds.sourceforge.net/post82.diff.gz post 0.82 patches] - updated 2009-03-02).&lt;br /&gt;
* PHP source files (tested with [http://www.php.net/get/php-5.2.6.tar.gz/from/a/mirror version 5.2.6])&lt;br /&gt;
* These packages (non-debug):&lt;br /&gt;
** From http://pecl2.php.net/downloads/php-windows-builds/php-libs/ :&lt;br /&gt;
*** binary-tools.zip&lt;br /&gt;
** From http://pecl2.php.net/downloads/php-windows-builds/php-libs/VC6/x86/ :&lt;br /&gt;
*** bindlib&lt;br /&gt;
*** libiconv&lt;br /&gt;
*** libxml&lt;br /&gt;
*** libxslt&lt;br /&gt;
*** zlib&lt;br /&gt;
&lt;br /&gt;
==Build Steps==&lt;br /&gt;
&lt;br /&gt;
* Create c:\dev&lt;br /&gt;
* Create c:\dev\php-build&lt;br /&gt;
* Uncompress all the packages listed in requirements and PHP into c:\dev\php-build (replacing all when uncompressing).&lt;br /&gt;
* Copy uncompressed [http://www.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-0.82.tar.gz freetds] folder to C:\dev\php-build (rename it to, simply, &amp;quot;freetds&amp;quot;).&lt;br /&gt;
* Apply [http://freetds.sourceforge.net/post82.diff.gz post 0.82 patches] in the &amp;quot;freetds&amp;quot; dir.&lt;br /&gt;
* Open the C:\dev\php-build\freetds\win32\msvc6\FreeTDS.dsw Project Workspace (it&#039;s really important to get this Workspace and not any of the individual projects!).&lt;br /&gt;
* In the &amp;quot;Build&amp;quot; menu, set the &amp;quot;Active Configuration&amp;quot; to  &amp;quot;dblib - Win32 Release&amp;quot; and then, in the same menu, &amp;quot;Rebuild All&amp;quot;. This should end with one dblib.lib library into C:\dev\php-build\freetd\win32\msvc6\db_Release&lt;br /&gt;
* Copy dblib.lib to C:\dev\php-build\lib&lt;br /&gt;
* Start CMD&lt;br /&gt;
* Create one C:\dev\prepare4php.bat file with contents below and execute it:&lt;br /&gt;
::@set PATH=C:\dev\php-build\bin;%PATH%&lt;br /&gt;
::@set INCLUDE=C:\dev\php-build\include;%INCLUDE%&lt;br /&gt;
::@set LIB=C:\dev\php-build\lib;%LIB%&lt;br /&gt;
::@set BISON_SIMPLE=C:\dev\php-build\bin\bison.simple&lt;br /&gt;
* Continue in CMD and change dir to C:\dev\php-build\php-x-x-x&lt;br /&gt;
* Execute this:&lt;br /&gt;
** buildconf&lt;br /&gt;
** cscript /nologo configure.js --disable-all --disable-ipv6  --enable-zts (--disable-zts)  --with-dblib=shared --enable-object-out-dir=c:\dev --with-extra-includes=c:\dev\php-build\freetds\include;c:\dev\php-build\freetds\win32&lt;br /&gt;
** nmake&lt;br /&gt;
* You should end with one C:\dev\Release_TS for the --enable-zts (or C:\dev\Release for the --disable-zts alternative)  dir, with your compiled FreeTDS PHP module ready at the root level of that dir.&lt;br /&gt;
&lt;br /&gt;
==Notes==&lt;br /&gt;
* By using --enable-zts or --disable-zts you&#039;ll end with different thread safe/no safe versions of the extension. Use them depending of your environment thread safety.&lt;br /&gt;
* If you one use PHP 5.2 version to build the lib, the extensions generated are expected to work against any PHP 5.2.x version (but not against other releases of PHP, like 5.1 or 5.3).&lt;br /&gt;
* MSVC 6.0 is required because it&#039;s the official tool used to build PHP binary distributions. It seems that, with PHP 5.3 they will start using MSVC 9 or so... corresponding extensions should use the same.&lt;br /&gt;
* Feel free to fix and improve this document. TIA! &lt;br /&gt;
* For any comment related to this, please use MDL-14725 in the Moodle Tracker.&lt;br /&gt;
* And MDL-11810 has a related discussion.&lt;br /&gt;
&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:XMLDB]]&lt;br /&gt;
[[Category:DB]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2754</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2754"/>
		<updated>2009-04-30T10:38:33Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Lists and Icons */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2753</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2753"/>
		<updated>2009-04-30T10:38:22Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Authorized Personnel Only */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2752</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2752"/>
		<updated>2009-04-30T10:37:53Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Eye Candy */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2751</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2751"/>
		<updated>2009-04-30T10:37:45Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* The Effects of Globalization */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2750</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2750"/>
		<updated>2009-04-30T10:36:54Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* We Are Legion */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2749</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2749"/>
		<updated>2009-04-30T10:36:26Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Configure That Out */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2748</id>
		<title>Blocks</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks&amp;diff=2748"/>
		<updated>2009-04-30T09:21:13Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* config_save() */&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 (pj@moodle.org)&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 reference 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;
== 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 behavior 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;
[[#top|Back to top of page]]&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|Back to top of page]]&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;
[[#top|Back to top of page]]&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;table&amp;amp;gt; element, 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;
== 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;
== 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|Back to top of page]]&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;
&lt;br /&gt;
[[Category:Blocks]]&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Desarrollo de bloques]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Compiling_FreeTDS_under_Windows&amp;diff=27813</id>
		<title>Talk:Compiling FreeTDS under Windows</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Compiling_FreeTDS_under_Windows&amp;diff=27813"/>
		<updated>2008-12-03T22:19:28Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Brilliant article, i finally managed to get 0.8.2 to build!&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Compiling_FreeTDS_under_Windows&amp;diff=27812</id>
		<title>Talk:Compiling FreeTDS under Windows</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Compiling_FreeTDS_under_Windows&amp;diff=27812"/>
		<updated>2008-12-03T20:23:57Z</updated>

		<summary type="html">&lt;p&gt;Afhole: New page: Brilliant article, i finally managed to get 0.8.2 to build! However the tests in test.php from: http://tracker.moodle.org/browse/MDL-11810 still fail for us, have you managed to get them a...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Brilliant article, i finally managed to get 0.8.2 to build!&lt;br /&gt;
However the tests in test.php from: http://tracker.moodle.org/browse/MDL-11810 still fail for us, have you managed to get them all to work ok?&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5806</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5806"/>
		<updated>2008-10-14T10:26:47Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* advcheckbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
==definition()==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc is all included in a function you must define in your class &#039;definition();&#039;&lt;br /&gt;
&lt;br /&gt;
definition() is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the defintion will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The definition() should include all elements that are going to be used on form, some elements may be removed or tweaked later in definition_after_data(). Please do not create conditional elements in definition(), the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a legend.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//-------------------------------------------------------------------------------&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
===button===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element. &lt;br /&gt;
&lt;br /&gt;
===checkbox===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple checkbox. The third param for this element is the label to display on the left side of the form. You can also supply a string as a fourth param to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
====advcheckbox====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(&#039;group&#039; =&amp;gt; 1), array(0, 1));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Similar to the checkbox above, but with a couple of important improvements:&lt;br /&gt;
&lt;br /&gt;
#The 5th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
#The 6th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
&lt;br /&gt;
===choosecoursefile===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039;=&amp;gt;null,//if it is null (default then use global $COURSE&lt;br /&gt;
 &#039;height&#039;=&amp;gt;500,// height of the popup window&lt;br /&gt;
 &#039;width&#039;=&amp;gt;750, // width of the popup window&lt;br /&gt;
&#039;options&#039;=&amp;gt;&#039;none&#039;);//options string for the pop up window &lt;br /&gt;
                   //eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===date_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;optional&#039;=&amp;gt;false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===date_time_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;step&#039;=&amp;gt;5);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===file===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
===hidden===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===htmleditor &amp;amp; format===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;text&#039;, get_string(&#039;choicetext&#039;, &#039;choice&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;text&#039;, PARAM_RAW);&lt;br /&gt;
	$mform-&amp;gt;addRule(&#039;text&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;format&#039;, &#039;format&#039;, get_string(&#039;format&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;canUseHtmlEditor&#039;=&amp;gt;&#039;detect&#039;,&#039;rows&#039;=&amp;gt;10, &#039;cols&#039;=&amp;gt;65, &lt;br /&gt;
&#039;width&#039;=&amp;gt;0,&#039;height&#039;=&amp;gt;0, &#039;course&#039;=&amp;gt;0);&lt;br /&gt;
//options same as print_textarea params&lt;br /&gt;
//use rows and cols options to control htmleditor size.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===radio===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $radioarray=array();&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
        $mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
====setDefault====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $select = &amp;amp;$mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
        $select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
                  get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        //normally you use add_action_buttons instead of this code&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;).&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text element. Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
        $attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $availablefromgroup=array();&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
        $mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=null)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the first argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be notchecked, checked, selected, eq or if it is anything else then we test for neq.&lt;br /&gt;
* If $condition is eq or neq then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
* If $condition is checked or notchecked then we check to see if a checkbox is checked or not.&lt;br /&gt;
* If $condition is selected then we check to see if a particular option is selected from a dropdown list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: I am not sure this section is complete. I just found and added one missing case, but there may be others--[[User:Tim Hunt|Tim Hunt]] 06:04, 15 October 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to be plain text. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will still *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide by Keith Edmunds of Midnighthax.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5805</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5805"/>
		<updated>2008-10-14T10:25:49Z</updated>

		<summary type="html">&lt;p&gt;Afhole: Undo revision 45308 by Afhole (Talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
==definition()==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc is all included in a function you must define in your class &#039;definition();&#039;&lt;br /&gt;
&lt;br /&gt;
definition() is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the defintion will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The definition() should include all elements that are going to be used on form, some elements may be removed or tweaked later in definition_after_data(). Please do not create conditional elements in definition(), the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a legend.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//-------------------------------------------------------------------------------&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
===button===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element. &lt;br /&gt;
&lt;br /&gt;
===checkbox===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple checkbox. The third param for this element is the label to display on the left side of the form. You can also supply a string as a fourth param to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
====advcheckbox====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(0, 1), array(&#039;group&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Similar to the checkbox above, but with a couple of important improvements:&lt;br /&gt;
&lt;br /&gt;
#The 5th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
#The 6th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
&lt;br /&gt;
===choosecoursefile===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039;=&amp;gt;null,//if it is null (default then use global $COURSE&lt;br /&gt;
 &#039;height&#039;=&amp;gt;500,// height of the popup window&lt;br /&gt;
 &#039;width&#039;=&amp;gt;750, // width of the popup window&lt;br /&gt;
&#039;options&#039;=&amp;gt;&#039;none&#039;);//options string for the pop up window &lt;br /&gt;
                   //eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===date_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;optional&#039;=&amp;gt;false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===date_time_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;step&#039;=&amp;gt;5);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===file===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
===hidden===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===htmleditor &amp;amp; format===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;text&#039;, get_string(&#039;choicetext&#039;, &#039;choice&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;text&#039;, PARAM_RAW);&lt;br /&gt;
	$mform-&amp;gt;addRule(&#039;text&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;format&#039;, &#039;format&#039;, get_string(&#039;format&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;canUseHtmlEditor&#039;=&amp;gt;&#039;detect&#039;,&#039;rows&#039;=&amp;gt;10, &#039;cols&#039;=&amp;gt;65, &lt;br /&gt;
&#039;width&#039;=&amp;gt;0,&#039;height&#039;=&amp;gt;0, &#039;course&#039;=&amp;gt;0);&lt;br /&gt;
//options same as print_textarea params&lt;br /&gt;
//use rows and cols options to control htmleditor size.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===radio===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $radioarray=array();&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
        $mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
====setDefault====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $select = &amp;amp;$mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
        $select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
                  get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        //normally you use add_action_buttons instead of this code&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;).&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text element. Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
        $attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $availablefromgroup=array();&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
        $mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=null)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the first argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be notchecked, checked, selected, eq or if it is anything else then we test for neq.&lt;br /&gt;
* If $condition is eq or neq then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
* If $condition is checked or notchecked then we check to see if a checkbox is checked or not.&lt;br /&gt;
* If $condition is selected then we check to see if a particular option is selected from a dropdown list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: I am not sure this section is complete. I just found and added one missing case, but there may be others--[[User:Tim Hunt|Tim Hunt]] 06:04, 15 October 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to be plain text. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will still *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide by Keith Edmunds of Midnighthax.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5804</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5804"/>
		<updated>2008-10-14T10:23:44Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* advcheckbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
==definition()==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc is all included in a function you must define in your class &#039;definition();&#039;&lt;br /&gt;
&lt;br /&gt;
definition() is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the defintion will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The definition() should include all elements that are going to be used on form, some elements may be removed or tweaked later in definition_after_data(). Please do not create conditional elements in definition(), the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a legend.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//-------------------------------------------------------------------------------&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
===button===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element. &lt;br /&gt;
&lt;br /&gt;
===checkbox===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple checkbox. The third param for this element is the label to display on the left side of the form. You can also supply a string as a fourth param to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
====advcheckbox====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(0, 1), array(&#039;group&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Similar to the checkbox above, but with a couple of important improvements:&lt;br /&gt;
&lt;br /&gt;
#The 5th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
#The 6th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
&lt;br /&gt;
===choosecoursefile===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039;=&amp;gt;null,//if it is null (default then use global $COURSE&lt;br /&gt;
 &#039;height&#039;=&amp;gt;500,// height of the popup window&lt;br /&gt;
 &#039;width&#039;=&amp;gt;750, // width of the popup window&lt;br /&gt;
&#039;options&#039;=&amp;gt;&#039;none&#039;);//options string for the pop up window &lt;br /&gt;
                   //eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===date_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;optional&#039;=&amp;gt;false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===date_time_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;step&#039;=&amp;gt;5);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===file===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
===hidden===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===htmleditor &amp;amp; format===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;text&#039;, get_string(&#039;choicetext&#039;, &#039;choice&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;text&#039;, PARAM_RAW);&lt;br /&gt;
	$mform-&amp;gt;addRule(&#039;text&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;format&#039;, &#039;format&#039;, get_string(&#039;format&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;canUseHtmlEditor&#039;=&amp;gt;&#039;detect&#039;,&#039;rows&#039;=&amp;gt;10, &#039;cols&#039;=&amp;gt;65, &lt;br /&gt;
&#039;width&#039;=&amp;gt;0,&#039;height&#039;=&amp;gt;0, &#039;course&#039;=&amp;gt;0);&lt;br /&gt;
//options same as print_textarea params&lt;br /&gt;
//use rows and cols options to control htmleditor size.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===radio===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $radioarray=array();&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
        $mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
====setDefault====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $select = &amp;amp;$mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
        $select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
                  get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        //normally you use add_action_buttons instead of this code&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;).&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text element. Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
        $attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $availablefromgroup=array();&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
        $mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=null)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the first argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be notchecked, checked, selected, eq or if it is anything else then we test for neq.&lt;br /&gt;
* If $condition is eq or neq then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
* If $condition is checked or notchecked then we check to see if a checkbox is checked or not.&lt;br /&gt;
* If $condition is selected then we check to see if a particular option is selected from a dropdown list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: I am not sure this section is complete. I just found and added one missing case, but there may be others--[[User:Tim Hunt|Tim Hunt]] 06:04, 15 October 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to be plain text. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will still *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide by Keith Edmunds of Midnighthax.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5803</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5803"/>
		<updated>2008-10-09T15:12:47Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* choosecoursefile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
==definition()==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc is all included in a function you must define in your class &#039;definition();&#039;&lt;br /&gt;
&lt;br /&gt;
definition() is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the defintion will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The definition() should include all elements that are going to be used on form, some elements may be removed or tweaked later in definition_after_data(). Please do not create conditional elements in definition(), the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a legend.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//-------------------------------------------------------------------------------&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
===button===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element. &lt;br /&gt;
&lt;br /&gt;
===checkbox===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple checkbox. The third param for this element is the label to display on the left side of the form. You can also supply a string as a fourth param to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
====advcheckbox====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(0, 1), array(&#039;group&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Similar to the checkbox above, but with a couple of important improvements:&lt;br /&gt;
&lt;br /&gt;
#The 5th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
#The 6th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
&lt;br /&gt;
===choosecoursefile===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039;=&amp;gt;null,//if it is null (default then use global $COURSE&lt;br /&gt;
 &#039;height&#039;=&amp;gt;500,// height of the popup window&lt;br /&gt;
 &#039;width&#039;=&amp;gt;750, // width of the popup window&lt;br /&gt;
&#039;options&#039;=&amp;gt;&#039;none&#039;);//options string for the pop up window &lt;br /&gt;
                   //eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===date_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;optional&#039;=&amp;gt;false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===date_time_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;step&#039;=&amp;gt;5);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===file===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
===hidden===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===htmleditor &amp;amp; format===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;text&#039;, get_string(&#039;choicetext&#039;, &#039;choice&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;text&#039;, PARAM_RAW);&lt;br /&gt;
	$mform-&amp;gt;addRule(&#039;text&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;format&#039;, &#039;format&#039;, get_string(&#039;format&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;canUseHtmlEditor&#039;=&amp;gt;&#039;detect&#039;,&#039;rows&#039;=&amp;gt;10, &#039;cols&#039;=&amp;gt;65, &lt;br /&gt;
&#039;width&#039;=&amp;gt;0,&#039;height&#039;=&amp;gt;0, &#039;course&#039;=&amp;gt;0);&lt;br /&gt;
//options same as print_textarea params&lt;br /&gt;
//use rows and cols options to control htmleditor size.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===radio===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $radioarray=array();&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
        $mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
====setDefault====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $select = &amp;amp;$mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
        $select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
                  get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        //normally you use add_action_buttons instead of this code&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;).&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text element. Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
        $attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $availablefromgroup=array();&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
        $mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=null)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the first argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be notchecked, checked, selected, eq or if it is anything else then we test for neq.&lt;br /&gt;
* If $condition is eq or neq then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
* If $condition is checked or notchecked then we check to see if a checkbox is checked or not.&lt;br /&gt;
* If $condition is selected then we check to see if a particular option is selected from a dropdown list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: I am not sure this section is complete. I just found and added one missing case, but there may be others--[[User:Tim Hunt|Tim Hunt]] 06:04, 15 October 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to be plain text. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will still *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide by Keith Edmunds of Midnighthax.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Data_manipulation_API&amp;diff=5161</id>
		<title>Data manipulation API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Data_manipulation_API&amp;diff=5161"/>
		<updated>2008-09-23T14:02:04Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}In this page you&#039;ll access to the available functions under Moodle to be able to access to DB data. You should use &#039;&#039;&#039;exclusively&#039;&#039;&#039; these functions in order to retrieve or modify DB contents because these functions provide an high level of abstraction and guarantee that your DB manipulation will work against different RDBMS.&lt;br /&gt;
&lt;br /&gt;
Where possible, tricks and examples will be documented here in order to make developers&#039; lives a bit easier. Of course, feel free to clarify, complete and add more info to all this documentation. It will be welcome, absolutely!&lt;br /&gt;
&lt;br /&gt;
== Main info ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note:&#039;&#039;&#039; All the functions showed in this page are for use in &#039;&#039;&#039;Moodle 2.0 upwards&#039;&#039;&#039;, where we changed the [[DB layer 2.0|DB layer]] to support some new features. If you need information for previous Moodle version, take a look to the [[DML functions - pre 2.0|DML functions - pre 2.0]] page.&lt;br /&gt;
&lt;br /&gt;
* All the function calls in this page are public methods of the $DB global object. So you&#039;ll need to &amp;quot;import&amp;quot; it within your functions (not needed in global scripts) with one simple:&lt;br /&gt;
&amp;lt;code php&amp;gt;global $DB;&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $table parameters in the functions are mean to be the table name &#039;&#039;&#039;without&#039;&#039; prefixes.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;&#039;1&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* When using the xxx_sql() functions, table names must be enclosed between curly braces.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE id = ?&#039;, array(1));&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $conditions parameters in the functions are arrays of fieldname=&amp;gt;fieldvalue elements.&lt;br /&gt;
&amp;lt;code php&amp;gt;$user = $DB-&amp;gt;get_record(&#039;user&#039;, array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
* All the $params parameters in the functions are arrays of values used to fill placeholders in SQL statements. Both question mark and named placeholders can be used.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/// Question mark placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = ? AND lastname = ?&#039;, &lt;br /&gt;
                       array(&#039;Martin&#039;, &#039;Dougiamas&#039;));&lt;br /&gt;
&lt;br /&gt;
/// Named placeholders:&lt;br /&gt;
   $DB-&amp;gt;get_record_sql(&#039;SELECT * FROM {user} WHERE firstname = :firstname AND lastname = :lastname&#039;,&lt;br /&gt;
                       array(&#039;firstname&#039;=&amp;gt;&#039;Martin&#039;, &#039;lastname&#039;=&amp;gt;&#039;Dougiamas&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The functions ==&lt;br /&gt;
&lt;br /&gt;
===Seeing how many records match a given criteria===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;count_records($table, array $conditions=null) &lt;br /&gt;
  /// Count the records in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;count_records_select($table, $select, array $params=null, $countitem=&amp;quot;COUNT(&#039;x&#039;)&amp;quot;) &lt;br /&gt;
  /// Count the records in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;count_records_sql($sql, array $params=null) &lt;br /&gt;
  /// Get the result of a SQL SELECT COUNT(...) query.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Seeing if one record exists===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;record_exists($table, array $conditions=null) &lt;br /&gt;
  /// Test whether a record exists in a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;record_exists_select($table, $select, array $params=null) &lt;br /&gt;
  /// Test whether any records exists in a table which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;record_exists_sql($sql, array $params=null) &lt;br /&gt;
  /// Test whether a SQL SELECT statement returns any records.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Retrieving a single record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_record($table, array $conditions, $fields=&#039;*&#039;, $ignoremultiple=false) &lt;br /&gt;
  /// Get a single database record as an object where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_record_select($table, $select, array $params=null, $fields=&#039;*&#039;, $ignoremultiple=false)&lt;br /&gt;
  /// Get a single database record as an object using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting an array of records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_records($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as an array of objects which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get a number of records as an array of objects using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_menu($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_records_select_menu($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_records_sql_menu($sql, array $params=null, $limitfrom=0, $limitnum=0)&lt;br /&gt;
  /// Get the first two columns from a number of records as an associative array using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_records_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as an array of objects where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from one record===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_field($table, $return, array $conditions)&lt;br /&gt;
  /// Get a single field value from a table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_field_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Get a single field value from a table record which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_field_sql($sql, array $params=null)&lt;br /&gt;
  /// Get a single field value (first field) using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Getting a particular field value from various records===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_select($table, $return, $select, array $params=null)&lt;br /&gt;
  /// Selects records and return values of chosen field as an array which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_fieldset_sql($sql, array $params=null)&lt;br /&gt;
  /// Selects records and return values (first field) as an array using a SQL statement.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Setting a particular field in the database===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;set_field($table, $newfield, $newvalue, array $conditions=null)&lt;br /&gt;
  /// Set a single field in every table record where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;set_field_select($table, $newfield, $newvalue, $select, array $params=null)&lt;br /&gt;
  /// Set a single field in every table record which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Deleting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;delete_records($table, array $conditions=null) &lt;br /&gt;
  /// Delete the records from a table where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;delete_records_select($table, $select, array $params=null)&lt;br /&gt;
  /// Delete one or more records from a table which match a particular WHERE clause.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Inserting Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;insert_record($table, $dataobject, $returnid=true, $bulk=false) &lt;br /&gt;
  /// Insert a record into a table and return the &amp;quot;id&amp;quot; field if required.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Updating Records===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;update_record($table, $dataobject, $bulk=false)&lt;br /&gt;
  /// Update a record in a table.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using Recordsets===&lt;br /&gt;
&lt;br /&gt;
While the number of records to be retrieved from DB is high, the &#039;&#039;&#039;get_records_xxx()&#039;&#039;&#039; functions above are far from optimal, because they use to load all the records in memory at the same time. Under those circumstances, it&#039;s highly recommended to use this &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions instead, using one nice mechanism to iterate over all the target records saving a lot of memory.&lt;br /&gt;
&lt;br /&gt;
Only one thing is &#039;&#039;&#039;absolutely important&#039;&#039;&#039;. Don&#039;t forget to close the record sets after using them! (that will freed a lot of resources in the RDBMS).&lt;br /&gt;
&lt;br /&gt;
Here it&#039;s the general way to iterate over records using the &#039;&#039;&#039;get_recordset_xxx()&#039;&#039;&#039; functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($rs = $DB-&amp;gt;get_recordset(....) {&lt;br /&gt;
    foreach ($rs as $record) {&lt;br /&gt;
     /// Do whatever you want with this record&lt;br /&gt;
    }&lt;br /&gt;
    $rs-&amp;gt;close(); /// Don&#039;t forget to close the recordset!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And this is the list of available functions (100% paired with the get_records_xxx() above):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;get_recordset($table, array $conditions=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where all the given conditions met.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_select($table, $select, array $params=null, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=0, $limitnum=0) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset which match a particular WHERE clause.&lt;br /&gt;
o $DB-&amp;gt;get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0);&lt;br /&gt;
  /// Get a number of records as a moodle_recordset using a SQL statement.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;get_recordset_list($table, $field=&#039;&#039;, $values=&#039;&#039;, $sort=&#039;&#039;, $fields=&#039;*&#039;, $limitfrom=&#039;&#039;, $limitnum=&#039;&#039;) &lt;br /&gt;
  /// Get a number of records as a moodle_recordset where one field match one list of values.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Functions===&lt;br /&gt;
&lt;br /&gt;
In order have real cross-db compatibility, there are some helper functions used to build SQL fragments based on the DB Moodle is running. Using them we&#039;ll avoid conditional queries here and there, having those &amp;quot;incompatibilities&amp;quot; fixed once and for ever.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
o $DB-&amp;gt;sql_bitand($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise AND &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitnot($int1) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise NOT &lt;br /&gt;
  /// operation with 1 integer.&lt;br /&gt;
o $DB-&amp;gt;sql_bitor($int1, $int2)&lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise OR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
o $DB-&amp;gt;sql_bitxor($int1, $int2) &lt;br /&gt;
  /// Returns the SQL text to be used in order to perform one bitwise XOR &lt;br /&gt;
  /// operation between 2 integers.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_null_from_clause()&lt;br /&gt;
  /// Returns the FROM clause required by some DBs in all SELECT statements.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_ceil($fieldname)&lt;br /&gt;
  /// Returns the correct CEIL expression applied to fieldname.&lt;br /&gt;
o $DB-&amp;gt;sql_substr()&lt;br /&gt;
  /// Returns the proper substr() function for each DB.&lt;br /&gt;
o $DB-&amp;gt;sql_ilike()&lt;br /&gt;
  /// Returns the proper SQL to do LIKE in a case-insensitive way.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2int($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to INTEGER.&lt;br /&gt;
o $DB-&amp;gt;sql_cast_char2real($fieldname, $text=false)&lt;br /&gt;
  /// Returns the SQL to be used in order to CAST one CHAR column to REAL number.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_compare_text($fieldname, $numchars=32) &lt;br /&gt;
  /// Returns the SQL text to be used to compare one TEXT (clob) column.&lt;br /&gt;
  /// with one VARCHAR column.&lt;br /&gt;
o $DB-&amp;gt;sql_order_by_text($fieldname, $numchars=32)&lt;br /&gt;
  /// Returns the SQL text to be used to order by one TEXT (clob) column.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_concat()&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed.&lt;br /&gt;
o $DB-&amp;gt;sql_concat_join($separator=&amp;quot;&#039; &#039;&amp;quot;, $elements=array())&lt;br /&gt;
  /// Returns the proper SQL to do CONCAT between the elements passed using one separator.&lt;br /&gt;
o $DB-&amp;gt;sql_fullname($first=&#039;firstname&#039;, $last=&#039;lastname&#039;)&lt;br /&gt;
  /// Returns the proper SQL to concatenate $firstname and $lastname.&lt;br /&gt;
 &lt;br /&gt;
o $DB-&amp;gt;sql_isempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is empty.&lt;br /&gt;
o $DB-&amp;gt;sql_isnotempty($tablename, $fieldname, $nullablefield, $textfield)&lt;br /&gt;
  /// Returns the proper SQL to know if one field is not empty.&lt;br /&gt;
o $DB-&amp;gt;sql_empty()&lt;br /&gt;
  /// Returns the empty string char used by every supported DB.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[DDL functions|DDL functions]]: Where all the functions used to handle DB objects ([[wikipedia:Data_Definition_Language|DDL]]) are defined.&lt;br /&gt;
* [[DML functions - pre 2.0|DML functions - pre 2.0]]: &#039;&#039;&#039;(deprecated!)&#039;&#039;&#039; For information valid before Moodle 2.0.&lt;br /&gt;
* [[DB layer 2.0 examples|DB layer 2.0 examples]]: To see some code examples using various DML functions.&lt;br /&gt;
* [[DB layer 2.0 migration docs|DB layer 2.0 migration docs]]: Information about how to modify your code to work with the new Moodle 2.0 DB layer.&lt;br /&gt;
&lt;br /&gt;
[[Category:DB]]&lt;br /&gt;
[[Category:XMLDB]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5802</id>
		<title>lib/formslib.php Form Definition</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=lib/formslib.php_Form_Definition&amp;diff=5802"/>
		<updated>2008-09-16T15:24:56Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* advcheckbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Formslib}}&lt;br /&gt;
==definition()==&lt;br /&gt;
&lt;br /&gt;
The definition of the elements to be included in the form, their &#039;types&#039; (PARAM_*), helpbuttons included, etc is all included in a function you must define in your class &#039;definition();&#039;&lt;br /&gt;
&lt;br /&gt;
definition() is used to define the elements in the form and &#039;&#039;&#039;this definition will be used for validating data submitted as well as for printing the form.&#039;&#039;&#039; For select and checkbox type elements only data that could have been selected will be allowed. And only data that corresponds to a form element in the defintion will be accepted as submitted data.&lt;br /&gt;
&lt;br /&gt;
The definition() should include all elements that are going to be used on form, some elements may be removed or tweaked later in definition_after_data(). Please do not create conditional elements in definition(), the definition() should not directly depend on the submitted data.&lt;br /&gt;
&lt;br /&gt;
==Use Fieldsets to group Form Elements==&lt;br /&gt;
&lt;br /&gt;
You use code like this to open a fieldset with a legend.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//-------------------------------------------------------------------------------&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;, &#039;nameforyourheaderelement&#039;, get_string(&#039;titleforlegened&#039;, &#039;modulename&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can&#039;t yet nest these visible fieldsets unfortunately. But in fact groups of elements are wrapped in invisible fieldsets.&lt;br /&gt;
&lt;br /&gt;
You close a fieldset with moodle_form&#039;s closeHeaderBefore method. You tell closeHeaderBefore the element before you wish to end the fieldset. A fieldset is automatically closed if you open a new one. You need to use this code only if you want to close a fieldset and the subsequent form elements are not to be enclosed by a visible fieldset (they are still enclosed with an invisibe one with no legend) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==addElement==&lt;br /&gt;
&lt;br /&gt;
Use the addElement method to add an element to a form. The first few arguments are always the same. The first param is the type of the element to add. The second is the elementname to use which is normally the html name of the element in the form. The third is often the text for the label for the element.&lt;br /&gt;
&lt;br /&gt;
Some examples are below :&lt;br /&gt;
===button===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;button&#039;, &#039;intro&#039;, get_string(&amp;quot;buttonlabel&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A button element. If you want a submit or cancel button see &#039;submit&#039; element. &lt;br /&gt;
&lt;br /&gt;
===checkbox===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;checkbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a simple checkbox. The third param for this element is the label to display on the left side of the form. You can also supply a string as a fourth param to specify a label that will appear on the right of the element. Checkboxes and radio buttons can be grouped and have individual labels on their right.&lt;br /&gt;
&lt;br /&gt;
====advcheckbox====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;advcheckbox&#039;, &#039;ratingtime&#039;, get_string(&#039;ratingtime&#039;, &#039;forum&#039;), &#039;Label displayed after checkbox&#039;, array(0, 1), array(&#039;group&#039; =&amp;gt; 1));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Similar to the checkbox above, but with a couple of important improvements:&lt;br /&gt;
&lt;br /&gt;
#The 5th parameter is a normal $attributes array, normally used to set HTML attributes for the &amp;lt;input&amp;gt; element. However, a special value of &#039;group&#039; can be given, which will add a class name to the element, and enable its grouping for a [[lib/formslib.php_add_checkbox_controller|checkbox controller]]&lt;br /&gt;
#The 6th parameter is an array of values that will be associated with the checked/unchecked state of the checkbox. With a normal checkbox you cannot choose that value, and in fact an unchecked checkbox will not even be sent with the form data.&lt;br /&gt;
&lt;br /&gt;
===choosecoursefile===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;choosecoursefile&#039;, &#039;mediafile&#039;, get_string(&#039;mediafile&#039;, &#039;lesson&#039;), array(&#039;courseid&#039;=&amp;gt;$COURSE-&amp;gt;id));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a file from the course files area. The fourth option is a list of options for the element. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;courseid&#039;=&amp;gt;null,\\if it is null (default then use globabl $COURSE&lt;br /&gt;
 &#039;height&#039;=&amp;gt;500,\\ height of the popup window&lt;br /&gt;
 &#039;width&#039;=&amp;gt;750, \\ width of the popup window&lt;br /&gt;
&#039;options&#039;=&amp;gt;&#039;none&#039;);\\options string for the pop up window &lt;br /&gt;
                   \\eg. &#039;menubar=0,location=0,scrollbars,resizable&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===date_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_selector&#039;, &#039;assesstimefinish&#039;, get_string(&#039;to&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a date selector. You can select a Day, Month and Year using a group of select boxes. The fourth param here is an array of options. The defaults for the options are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;optional&#039;=&amp;gt;false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===date_time_selector===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;assesstimestart&#039;, get_string(&#039;from&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a group of select boxes to select a date (Day Month and Year) and time (Hour and Minute). When submitted, submitted data is processed and a timestamp is passed to $form-&amp;gt;get_data(); the fourth param here is an array of options. The defaults for the options are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&#039;startyear&#039;=&amp;gt;1970, &#039;stopyear&#039;=&amp;gt;2020,&lt;br /&gt;
                    &#039;timezone&#039;=&amp;gt;99, &#039;applydst&#039;=&amp;gt;true, &#039;step&#039;=&amp;gt;5);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override these defaults by supplying an array as fourth param with one or more keys with a value to override the default. You can supply a fifth param of attributes here as well.&lt;br /&gt;
&lt;br /&gt;
===file===&lt;br /&gt;
&lt;br /&gt;
File upload input box with browse button. In the form definition type&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
after form submission and validation use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need advanced settings such as required file, different max upload size or name of uploaded file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;set_upload_manager(new upload_manager(&#039;attachment&#039;, true, false, $COURSE, false, 0, true, true, false));&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;file&#039;, &#039;attachment&#039;, get_string(&#039;attachment&#039;, &#039;forum&#039;));&lt;br /&gt;
            $mform-&amp;gt;addRule(&#039;attachment&#039;, null, &#039;required&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            if ($data = $mform-&amp;gt;get_data()) {&lt;br /&gt;
              ...&lt;br /&gt;
              $mform-&amp;gt;save_files($destination_directory);&lt;br /&gt;
              $newfilename = $mform-&amp;gt;get_new_filename();&lt;br /&gt;
              ...&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When porting old code it is also possible to use the upload manager directly for processing of uploaded files.&lt;br /&gt;
&lt;br /&gt;
Please note that if using set_upload_manager() it must be before addElement(&#039;file&#039;,..).&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
File uploading was rewritten in 2.0. Please see inline docs for now. This page will be updated when the new API stabilises.&lt;br /&gt;
&lt;br /&gt;
===filepicker===&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
General replacement of &#039;&#039;file&#039;&#039; element.&lt;br /&gt;
&lt;br /&gt;
===hidden===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;reply&#039;, &#039;yes&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A hidden element. Set the element name (in this case &#039;&#039;&#039;reply&#039;&#039;&#039;) to the stated value (in this case &#039;&#039;&#039;yes&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
===htmleditor &amp;amp; format===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;text&#039;, get_string(&#039;choicetext&#039;, &#039;choice&#039;));&lt;br /&gt;
        $mform-&amp;gt;setType(&#039;text&#039;, PARAM_RAW);&lt;br /&gt;
	$mform-&amp;gt;addRule(&#039;text&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;format&#039;, &#039;format&#039;, get_string(&#039;format&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can supply a fourth param to htmleditor of an array of options :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&#039;canUseHtmlEditor&#039;=&amp;gt;&#039;detect&#039;,&#039;rows&#039;=&amp;gt;10, &#039;cols&#039;=&amp;gt;65, &lt;br /&gt;
&#039;width&#039;=&amp;gt;0,&#039;height&#039;=&amp;gt;0, &#039;course&#039;=&amp;gt;0);&lt;br /&gt;
//options same as print_textarea params&lt;br /&gt;
//use rows and cols options to control htmleditor size.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===modgrade===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;modgrade&#039;, &#039;scale&#039;, get_string(&#039;grade&#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This is a custom element for selecting a grade for any activity module. The fourth argument is whether to include an option for no grade which has a value 0. This select box does include scales. The default is true, include no grade option.&lt;br /&gt;
&lt;br /&gt;
A helpbutton is automatically added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===password===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;password&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===passwordunmask===&lt;br /&gt;
{{Moodle 1.9}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;passwordunmask&#039;, &#039;password&#039;, get_string(&#039;label&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A password element with option to show the password in plaintext. Fourth param is an array or string of attributes.&lt;br /&gt;
&lt;br /&gt;
===radio===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $radioarray=array();&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;yes&#039;), 1, $attributes);&lt;br /&gt;
        $radioarray[] = &amp;amp;MoodleQuickForm::createElement(&#039;radio&#039;, &#039;yesno&#039;, &#039;&#039;, get_string(&#039;no&#039;), 0, $attributes);&lt;br /&gt;
        $mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Second param names the radio button and should be the same for each button in the group in order to toggle correctly. Third param would be the label for the form element but is generally ignored as this element will always be in a group which has it&#039;s own label. Fourth param is a string, a label to be displayed on the right of the element. The fifth is the value for this radio button. $attributes can be a string or an array of attributes.&lt;br /&gt;
&lt;br /&gt;
It is possible to add help to individual radio buttons but this requires a custom template to be defined for the group elements. See MDL-15571.&lt;br /&gt;
&lt;br /&gt;
====setDefault====&lt;br /&gt;
&lt;br /&gt;
To set the default for a radio button group as above use the following :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;yesno&#039;, 0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This would make the default &#039;no&#039;.&lt;br /&gt;
&lt;br /&gt;
===select===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;type&#039;, get_string(&#039;forumtype&#039;, &#039;forum&#039;), $FORUM_TYPES, $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth param for this element is an array of options for the select box. The keys are the values for the option and the value of the array is the text for the option. The fifth param $attributes is optional, see text element for description of attributes param.&lt;br /&gt;
&lt;br /&gt;
====multi-select====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $select = &amp;amp;$mform-&amp;gt;addElement(&#039;select&#039;, &#039;colors&#039;, get_string(&#039;colors&#039;), array(&#039;red&#039;, &#039;blue&#039;, &#039;green&#039;), $attributes);&lt;br /&gt;
        $select-&amp;gt;setMultiple(true);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===selectyesno===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;maxbytes&#039;, get_string(&#039;maxattachmentsize&#039;, &#039;forum&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want a yes / no select box this one automatically translates itself and has value 1 for yes and 0 for no.&lt;br /&gt;
&lt;br /&gt;
===static===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         $mform-&amp;gt;addElement(&#039;static&#039;, &#039;description&#039;, get_string(&#039;description&#039;, &#039;exercise&#039;),&lt;br /&gt;
                  get_string(&#039;descriptionofexercise&#039;, &#039;exercise&#039;, $COURSE-&amp;gt;students));&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a static element. It should be used with care it is used to display a static piece of text with a label. The third param is the label and the fourth is the static text itself.&lt;br /&gt;
&lt;br /&gt;
===submit, reset and cancel===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        //normally you use add_action_buttons instead of this code&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;reset&#039;, &#039;resetbutton&#039;, get_string(&#039;revert&#039;));&lt;br /&gt;
        $buttonarray[] = &amp;amp;$mform-&amp;gt;createElement(&#039;cancel&#039;);&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
        $mform-&amp;gt;closeHeaderBefore(&#039;buttonar&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;Submit&#039; type element is a submit type form element which will submit the form. A &#039;Reset&#039; will not submit the form but will reset any changes the user has made to form contents. A &#039;Cancel&#039; element cancels form submission. You need to have a branch in your code before you check for get_data() to check if submission has been cancelled with is_cancelled(); See the example on the usage page.&lt;br /&gt;
&lt;br /&gt;
You should name your submit and reset buttons &#039;submitbutton&#039; and &#039;resetbutton&#039; or something similar (not &#039;submit&#039; and &#039;reset&#039;). This avoids problems in JavaScript of collisions between form element names and names of JavaScript methods of the form object.&lt;br /&gt;
&lt;br /&gt;
====add_action_buttons($cancel = true, $submitlabel=null);====&lt;br /&gt;
&lt;br /&gt;
You will normally use this helper function which is a method of moodleform to add all the &#039;action&#039; buttons to the end of your form. A boolean parameter allow you to specify whether to include a cancel button and specify the label for your submit button (pass the result of get_string). Default for the submit button label is get_string(&#039;savechanges&#039;).&lt;br /&gt;
&lt;br /&gt;
===text===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;text&#039;, &#039;name&#039;, get_string(&#039;forumname&#039;, &#039;forum&#039;), $attributes);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a simple text element. Your fourth parameter here can be a string or array of attributes for the text element. The following are equivalent :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $attributes=&#039;size=&amp;quot;20&amp;quot;&#039;;&lt;br /&gt;
        $attributes=array(&#039;size&#039;=&amp;gt;&#039;20&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Generally you are encouraged to use CSS instead of using attributes for styling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A format element can be used as a format select box. It will be non-selectable if you&#039;re using an html editor.&lt;br /&gt;
&lt;br /&gt;
The third param for this element is $useHtmlEditor and it defaults to null in which case an html editor is used if the browser and user profile support it.&lt;br /&gt;
&lt;br /&gt;
===textarea===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;addElement(&#039;textarea&#039;, &#039;introduction&#039;, get_string(&amp;quot;introtext&amp;quot;, &amp;quot;survey&amp;quot;), &#039;wrap=&amp;quot;virtual&amp;quot; rows=&amp;quot;20&amp;quot; cols=&amp;quot;50&amp;quot;&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A textarea element. If you want an htmleditor use htmleditor element. Fourth element here is a string or array of attributes.&lt;br /&gt;
&lt;br /&gt;
==addGroup==&lt;br /&gt;
&lt;br /&gt;
A &#039;group&#039; in formslib is just a group of elements that will have a label and will be included on one line. &lt;br /&gt;
&lt;br /&gt;
For example typical code to include a submit and cancel button on the same line : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $buttonarray=array();&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;submitbutton&#039;, get_string(&#039;savechanges&#039;));&lt;br /&gt;
        $buttonarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;submit&#039;, &#039;cancel&#039;, get_string(&#039;cancel&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($buttonarray, &#039;buttonar&#039;, &#039;&#039;, array(&#039; &#039;), false);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the same arguments for createElement as you do for addElement. Any label for the element in the third argument is normally ignored (but not in the case of the submit buttons above where the third argument is not for a label but is the text for the button).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of putting a date_selector (which is itself a group of elements) and a checkbox on the same line, note that you can disable every element in the group using the group name &#039;availablefromgroup&#039; but it doesn&#039;t disable the controlling element the &#039;availablefromenabled&#039; checkbox:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $availablefromgroup=array();&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;date_selector&#039;, &#039;availablefrom&#039;, &#039;&#039;);&lt;br /&gt;
	$availablefromgroup[] =&amp;amp; $mform-&amp;gt;createElement(&#039;checkbox&#039;, &#039;availablefromenabled&#039;, &#039;&#039;, get_string(&#039;enable&#039;));&lt;br /&gt;
        $mform-&amp;gt;addGroup($availablefromgroup, &#039;availablefromgroup&#039;, get_string(&#039;availablefromdate&#039;, &#039;data&#039;), &#039;&amp;amp;nbsp;&#039;, false);&lt;br /&gt;
        $mform-&amp;gt;disabledIf(&#039;availablefromgroup&#039;, &#039;availablefromenabled&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==setHelpButton==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            $mform-&amp;gt;setHelpButton(&#039;lessondefault&#039;, array(&#039;lessondefault&#039;, get_string(&#039;lessondefault&#039;, &#039;lesson&#039;), &#039;lesson&#039;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
First param is an elementname and the second param is an array of params that are passed to helpbutton in weblib.php. Params are :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 * @param string $page  The keyword that defines a help page&lt;br /&gt;
 * @param string $title The title of links, rollover tips, alt tags etc&lt;br /&gt;
 *           &#039;Help with&#039; (or the language equivalent) will be prefixed and &#039;...&#039; will be stripped.&lt;br /&gt;
 * @param string $module Which module is the page defined in&lt;br /&gt;
 * @param mixed $image Use a help image for the link?  (true/false/&amp;quot;both&amp;quot;)&lt;br /&gt;
 * @param boolean $linktext If true, display the title next to the help icon.&lt;br /&gt;
 * @param string $text If defined then this text is used in the page, and&lt;br /&gt;
 *           the $page variable is ignored.&lt;br /&gt;
 * @param boolean $return If true then the output is returned as a string, if false it is printed to the current page.&lt;br /&gt;
 * @param string $imagetext The full text for the helpbutton icon. If empty use default help.gif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Make sure you don&#039;t set boolean $return to false. &lt;br /&gt;
&lt;br /&gt;
You need to do use this method after addElement();&lt;br /&gt;
&lt;br /&gt;
==setDefault==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;select&#039;, &#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), $grades);&lt;br /&gt;
        $mform-&amp;gt;setHelpButton(&#039;grade&#039;, array(&#039;grade&#039;, get_string(&#039;gradeforsubmission&#039;, &#039;exercise&#039;), &#039;exercise&#039;));&lt;br /&gt;
        $mform-&amp;gt;setDefault(&#039;grade&#039;, 100);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the default of the form value with setDefault($elementname, $value); where elementname is the elementname whose default you want to set and $value is the default to set. We set the defaults for the form in definition(). This default is what is used if no data is loaded into the form with set_data(); eg. on display of the form for an &#039;add&#039; rather than &#039;update&#039; function.&lt;br /&gt;
&lt;br /&gt;
==disabledIf==&lt;br /&gt;
&lt;br /&gt;
For any element or groups of element in a form you can conditionally disable the group or individual element depending on conditions.&lt;br /&gt;
&lt;br /&gt;
You can use $mform-&amp;gt;disabledIf($elementName, $dependentOn, $condition = &#039;notchecked&#039;, $value=null)&lt;br /&gt;
&lt;br /&gt;
* elementname can be a group. If you specify a group all elements in the group will be disabled (if dependentOn is in elementname group that is ignored and not disabled). These are the element names you&#039;ve used as the first argument in addElement or addGroup.&lt;br /&gt;
* dependentOn is the actual name of the element as it will appear in html. This can be different to the name used in addGroup particularly but also addElement where you&#039;re adding a complex element like a date_selector. Check the html of your page. You typically make the depedentOn a checkbox or select box.&lt;br /&gt;
* $condition will be notchecked, checked, selected, eq or if it is anything else then we test for neq.&lt;br /&gt;
* If $condition is eq or neq then we check the value of the dependentOn field and check for equality (==) or nonequality (!=) in js&lt;br /&gt;
* If $condition is checked or notchecked then we check to see if a checkbox is checked or not.&lt;br /&gt;
* If $condition is selected then we check to see if a particular option is selected from a dropdown list.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: I am not sure this section is complete. I just found and added one missing case, but there may be others--[[User:Tim Hunt|Tim Hunt]] 06:04, 15 October 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==setType==&lt;br /&gt;
&lt;br /&gt;
PARAM_* types are used to specify how a submitted variable should be cleaned. These should be used for get parameters such as id, course etc. which are used to load a page and also with setType(); method. Every form element should have a type specified except select, radio box and checkbox elements, these elements do a good job of cleaning themselves (only specified options are allowed as user input).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Most Commonly Used PARAM_* Types===&lt;br /&gt;
&lt;br /&gt;
These are the most commonly used PARAM_* types and their proper uses. More types can be seen in moodlelib.php starting around line 100.&lt;br /&gt;
&lt;br /&gt;
* PARAM_CLEAN is deprecated and you should try to use a more specific type.&lt;br /&gt;
* PARAM_TEXT should be used for cleaning data that is expected to be plain text. It will strip all html tags. But will still let tags for multilang support through.&lt;br /&gt;
* PARAM_NOTAGS should be used for cleaning data that is expected to be plain text. It will strip *all* html type tags. It will still *not* let tags for multilang support through. This should be used for instance for email addresses where no multilang support is appropriate.&lt;br /&gt;
* PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the html editor. Data from the editor is later cleaned before display using format_text() function. PARAM_RAW can also be used for data that is validated by some other way or printed by p() or s().&lt;br /&gt;
* PARAM_INT should be used for integers.&lt;br /&gt;
* PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying form actions.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
* [http://midnighthax.com/quickform.php PEAR HTML QuickForm Getting Started Guide by Keith Edmunds of Midnighthax.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Formslib]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7376</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7376"/>
		<updated>2008-08-26T14:49:50Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
        ///Display the resource&lt;br /&gt;
        &lt;br /&gt;
        global $CFG;&lt;br /&gt;
        parent::display();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function add_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7375</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7375"/>
		<updated>2008-08-26T14:39:05Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Create a new resource type */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
        ///Display the resource&lt;br /&gt;
        &lt;br /&gt;
        global $CFG;&lt;br /&gt;
        parent::display();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function add_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7374</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7374"/>
		<updated>2008-08-26T14:38:44Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* Create a new resource type */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
        ///Display the resource&lt;br /&gt;
        &lt;br /&gt;
        global $CFG;&lt;br /&gt;
        parent::display();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function add_instance($resource)&lt;br /&gt;
	{&lt;br /&gt;
        return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7373</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7373"/>
		<updated>2008-08-26T14:17:55Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
        ///Display the resource&lt;br /&gt;
        &lt;br /&gt;
        global $CFG;&lt;br /&gt;
        parent::display();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    function add_instance($resource) {&lt;br /&gt;
        return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7372</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7372"/>
		<updated>2008-08-26T14:16:26Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
		///Display the resource&lt;br /&gt;
		&lt;br /&gt;
        global $CFG;&lt;br /&gt;
	    parent::display();&lt;br /&gt;
    }&lt;br /&gt;
	&lt;br /&gt;
    function add_instance($resource) {&lt;br /&gt;
	    return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource)&lt;br /&gt;
	{&lt;br /&gt;
	    return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource)&lt;br /&gt;
	{&lt;br /&gt;
	    return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform)&lt;br /&gt;
	{&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values)&lt;br /&gt;
	{&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7371</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7371"/>
		<updated>2008-08-26T14:15:29Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
		///Display the resource&lt;br /&gt;
		&lt;br /&gt;
        global $CFG;&lt;br /&gt;
	    parent::display();&lt;br /&gt;
    }&lt;br /&gt;
	&lt;br /&gt;
	function add_instance($resource) {&lt;br /&gt;
	    return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    function update_instance($resource) {&lt;br /&gt;
	    return parent::update_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function delete_instance($resource) {&lt;br /&gt;
	    return parent::delete_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_elements(&amp;amp;$mform) {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function setup_preprocessing(&amp;amp;$default_values){&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7370</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7370"/>
		<updated>2008-08-26T14:11:25Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
	///Display the resource&lt;br /&gt;
        global $CFG;&lt;br /&gt;
	parent::display();&lt;br /&gt;
    }&lt;br /&gt;
    function add_instance($resource)&lt;br /&gt;
    {&lt;br /&gt;
        return parent::add_instance($resource);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7369</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7369"/>
		<updated>2008-08-22T10:16:00Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
	///Display the resource&lt;br /&gt;
        global $CFG;&lt;br /&gt;
	parent::display();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7368</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7368"/>
		<updated>2008-08-22T10:15:44Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function display()&lt;br /&gt;
    {&lt;br /&gt;
		///Display the resource&lt;br /&gt;
		&lt;br /&gt;
        global $CFG;&lt;br /&gt;
	    parent::display();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7367</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7367"/>
		<updated>2008-08-22T09:27:48Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
    function resource_new($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7366</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7366"/>
		<updated>2008-08-22T09:26:45Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
== Create a new resource type ==&lt;br /&gt;
&lt;br /&gt;
To create a new resource type, of name &#039;new&#039;; create a folder in /mod/resource/type&lt;br /&gt;
And create the resource.class.php file: /mod/resource/type/new/resource.class.php&lt;br /&gt;
&lt;br /&gt;
Structure of resource.class.php:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
    function resource_text($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7365</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7365"/>
		<updated>2008-08-22T09:23:03Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type/&amp;lt;new&amp;gt;&lt;br /&gt;
&lt;br /&gt;
File(s) required: resource.class.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
    function resource_text($cmid=0)&lt;br /&gt;
    {&lt;br /&gt;
        parent::resource_base($cmid);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7364</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7364"/>
		<updated>2008-08-21T10:24:54Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type/&amp;lt;new&amp;gt;&lt;br /&gt;
&lt;br /&gt;
File(s) required: resource.class.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_new extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7363</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7363"/>
		<updated>2008-08-21T10:22:44Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type/&amp;lt;new&amp;gt;&lt;br /&gt;
&lt;br /&gt;
File(s) required: resource.class.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class resource_&amp;lt;new&amp;gt; extends resource_base&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7362</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7362"/>
		<updated>2008-08-21T10:05:19Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;br /&gt;
&lt;br /&gt;
File(s) required: resource.class.php&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7361</id>
		<title>Resource types</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Resource_types&amp;diff=7361"/>
		<updated>2008-08-21T10:04:38Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Resource types]]&lt;br /&gt;
[[Category:Resource]]&lt;br /&gt;
&lt;br /&gt;
Resource types are located in the folder /mod/resource/type&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Theme_directory_guide&amp;diff=5456</id>
		<title>Theme directory guide</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Theme_directory_guide&amp;diff=5456"/>
		<updated>2007-01-15T15:11:00Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Themes}}&lt;br /&gt;
&lt;br /&gt;
In the standard Moodle distribution, all themes are placed in the theme/ directory, this leads to developers hardcoding this location into their themes and references to themes. Developers should not take this location for granted, instead using the variables which moodle provides for the purpose of specifying a theme location.&lt;br /&gt;
&lt;br /&gt;
Starting with 1.7, moodle will fully support changing the location in which themes are stored. Developers need to ensure they are using the provided variables to ensure compatibility with this feature.&lt;br /&gt;
&lt;br /&gt;
== $CFG-&amp;gt;themewww ==&lt;br /&gt;
&#039;&#039;&#039;This variable has been available since version 1.5.1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;$CFG-&amp;gt;themewww&#039;&#039; variable contains the web-accessible location of the theme directory. If it is not set by the site administrator it will be the default of $CFG-&amp;gt;wwwroot . &#039;/theme&#039;. i.e. &#039;http://my.moodle.site/theme&#039;.&lt;br /&gt;
&lt;br /&gt;
== $CFG-&amp;gt;httpsthemewww ==&lt;br /&gt;
{{Moodle 1.7}}&lt;br /&gt;
&#039;&#039;&#039;This variable will be introduced in version 1.7&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;$CFG-&amp;gt;httpsthemewww&#039;&#039; variable contains the same information as $CFG-&amp;gt;themewww with the correct http/https prefix. This  should be used to provide proper references to files on pages which could be https protected.&lt;br /&gt;
&lt;br /&gt;
== $CFG-&amp;gt;themedir ==&lt;br /&gt;
&#039;&#039;&#039;This variable has been available since 1.5.1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;$CFG-&amp;gt;themedir&#039;&#039; variable contains the local location on the moodle server of the theme directory. If it is not set by the site administrator it will be the default of $CFG-&amp;gt;dirroot . &#039;/theme&#039;. i.e. &#039;/my/moodle/location/theme&#039;.&lt;br /&gt;
&lt;br /&gt;
== How to refer to the directory of the current theme ==&lt;br /&gt;
The most common use of the theme directories will be used to specify the current theme directory for inclusion/display of files.&lt;br /&gt;
&lt;br /&gt;
The correct way to specify the http path to the directory is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;themewww .&#039;/&#039;. current_theme()  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The exception to this is when specifying http theme paths which might be displayed on secure pages. In order to specify the http path to the theme directory (allow for a secure url), developers should use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;httpsthemewww .&#039;/&#039;. current_theme()  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to refer to the local path to theme files, developers should use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;themedir .&#039;/&#039;. current_theme()  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Wiki_2.0&amp;diff=1684</id>
		<title>Wiki 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Wiki_2.0&amp;diff=1684"/>
		<updated>2006-11-27T16:01:22Z</updated>

		<summary type="html">&lt;p&gt;Afhole: /* New wiki */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Moodle wiki(s) enables participants to work together on web pages to add, expand and change the content.  This page can serve to provide information about different Wikis that may be used with Moodle.  &lt;br /&gt;
&lt;br /&gt;
= Wiki Standard =&lt;br /&gt;
Link to the [[Wiki]] MoodleDoc page&lt;br /&gt;
This is the standard Wiki which is part of 1.6 .  It was developed from a version of Erfurt wiki. &lt;br /&gt;
See [http://moodle.org/help.php?module=wiki&amp;amp;file=howtowiki.html &amp;quot;How to wiki&amp;quot; page for more information].&lt;br /&gt;
&lt;br /&gt;
Built by Mike Churchward &amp;amp; Michael Schneider&lt;br /&gt;
= Dfwiki =&lt;br /&gt;
This is an addin wiki for Moodle.&lt;br /&gt;
[[Dfwiki]] is the MoodleDoc page.&lt;br /&gt;
&#039;&#039;&#039;DFWiki&#039;&#039;&#039; is an alternative [[wiki]] module to the current (1.5.3) Moodle [[Wiki module]].&lt;br /&gt;
&lt;br /&gt;
Dfwiki for Moodle 1.5.3 can be found [http://appserv.lsi.upc.es/palangana/moodle/course/view.php?id=15 in dfwiki home page], and in the Moodle [[CVS]]. The [http://appserv.lsi.upc.es/palangana/moodle/course/view.php?id=15 dfwiki english home page is here].&lt;br /&gt;
&lt;br /&gt;
Team leader is Marc Alier (Ludo).&lt;br /&gt;
&lt;br /&gt;
= Erfurt wiki =&lt;br /&gt;
Named for the developer&#039;s hometown in Germany, it was the basis for the standard wiki included with Moodle.&lt;br /&gt;
&lt;br /&gt;
= New wiki =&lt;br /&gt;
Works for 1.6.x. Adoption for 1.7 in progress November 2006. We ([[Dfwiki_module#Dfwikiteam|Dfwiki team]]) hope it will be on 1.8 -Team leader Marc Alier (ludo) &lt;br /&gt;
==Tiddlywiki integration==&lt;br /&gt;
New wiki can interoperate with the Ajax based portable [http://tiddlywiki.com tidlywiki].&lt;br /&gt;
See [[Tiddlywiki integration]]&lt;br /&gt;
&lt;br /&gt;
= MediaWiki =&lt;br /&gt;
This is the &amp;quot;big&amp;quot; wiki.  Will Taylor says &amp;quot;I have MediaWiki integrated now with Moodle versions 1.5.3 and 1.6, very easy to set up.  Users need to log in separately to MediaWiki to edit, but they are authenticated off the Moodle database, so use the same username &amp;amp; password without needing to create a separate account on MediaWiki.  Using the MediaWiki permissions system, I have editing privileges reserved for registered, logged-in users, and read privileges open to the world - but you could configure this in many ways if you wish.  Check out the various projects created in MediaWiki (WikiPedia, Wiktionary, &amp;amp;c.) to see the potential of this platform.&amp;quot;  &lt;br /&gt;
&lt;br /&gt;
MediaWiki should be used as a &#039;&#039;&#039;site-specific&#039;&#039;&#039; wiki. The standard Moodle wiki, or Dfwiki should be used as course-specific wiki. &lt;br /&gt;
= Table of Versions =&lt;br /&gt;
{| border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;4&amp;quot; cellspacing =&amp;quot;0&amp;quot; rules=&amp;quot;all&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Wikis in Moodle&#039;&#039;&#039;&lt;br /&gt;
! -Version Name-  &lt;br /&gt;
! Wiki version&lt;br /&gt;
! Moodle ver&lt;br /&gt;
! Status&lt;br /&gt;
! Download Place&lt;br /&gt;
! Docs&lt;br /&gt;
! Discussion Place&lt;br /&gt;
! Feature1&lt;br /&gt;
|-----&lt;br /&gt;
| Std Wiki&lt;br /&gt;
| &lt;br /&gt;
| all&lt;br /&gt;
|&lt;br /&gt;
|[http://moodle.org/mod/data/view.php?d=13&amp;amp;rid=273 Modules]&lt;br /&gt;
| [[Wiki]]&lt;br /&gt;
| [http://moodle.org/mod/forum/view.php?f=366 Wiki forum]&lt;br /&gt;
|&lt;br /&gt;
|-----&lt;br /&gt;
| Dfwiki&lt;br /&gt;
|&lt;br /&gt;
| 1.5.3&lt;br /&gt;
|&lt;br /&gt;
|[[http://moodle.org/mod/data/view.php?d=13&amp;amp;rid=115 CVS Page]]&lt;br /&gt;
| [[Dfwiki]]&lt;br /&gt;
|[http://moodle.org/mod/forum/view.php?f=366 Wiki forum]&lt;br /&gt;
|&lt;br /&gt;
|-----&lt;br /&gt;
| Erfurt Wiki&lt;br /&gt;
| &lt;br /&gt;
| 1.6&lt;br /&gt;
|&lt;br /&gt;
|[http://erfurtwiki.sourceforge.net/ Sourceforge]&lt;br /&gt;
| [http://erfurtwiki.sourceforge.net/README readme]&lt;br /&gt;
|&lt;br /&gt;
| &lt;br /&gt;
|-----&lt;br /&gt;
| New wiki&lt;br /&gt;
| &lt;br /&gt;
|1.6&lt;br /&gt;
|Beta&lt;br /&gt;
|&lt;br /&gt;
|[http://appserv.lsi.upc.es/palangana/moodle/course/view.php?id=15 DFwiki home]&lt;br /&gt;
|[http://appserv.lsi.upc.es/palangana/moodle/course/view.php?id=15 DFwiki home]&lt;br /&gt;
|&lt;br /&gt;
|-----&lt;br /&gt;
| MediaWiki&lt;br /&gt;
| &lt;br /&gt;
|NA&lt;br /&gt;
|&lt;br /&gt;
|[http://www.mediawiki.org/wiki/MediaWiki MediaWiki Home]&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Dfwiki]]&lt;br /&gt;
* [[Wiki requirements|Specific wiki requirements]]&lt;br /&gt;
* [[dfwiki requests]]&lt;br /&gt;
* [[Wiki comments |Wiki development comments]]&lt;br /&gt;
*[[wikindx]] for developers&lt;br /&gt;
&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/view.php?f=366 Wiki module forum]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Wiki]]&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:Mnet_Web_services_API&amp;diff=26987</id>
		<title>Talk:Mnet Web services API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:Mnet_Web_services_API&amp;diff=26987"/>
		<updated>2006-06-08T15:03:27Z</updated>

		<summary type="html">&lt;p&gt;Afhole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Is there any information regarding the current status of development?&lt;/div&gt;</summary>
		<author><name>Afhole</name></author>
	</entry>
</feed>