<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/30/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Azoltay</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/30/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Azoltay"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/Special:Contributions/Azoltay"/>
	<updated>2026-04-21T20:00:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/30/en/index.php?title=Enrolment&amp;diff=84646</id>
		<title>Enrolment</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/index.php?title=Enrolment&amp;diff=84646"/>
		<updated>2011-06-08T23:40:03Z</updated>

		<summary type="html">&lt;p&gt;Azoltay: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Course Administration block&amp;gt;Settings&amp;gt;Enrolment&lt;br /&gt;
&lt;br /&gt;
Enrolment is the process of assigning users to roles (usually student) in a course. There are 3  types: internal enrolment, manual enrolment and enrollment plugins.&lt;br /&gt;
&lt;br /&gt;
==Internal enrolment==&lt;br /&gt;
By default, [[Internal enrolment|internal enrolment]] is where any student can enrol themselves into a course. A course can ask an student trying to enrol for an [[Enrolment key|enrolment key]], which can be set in the course settings. &lt;br /&gt;
&lt;br /&gt;
Moodle also provides a number of other enrolment methods, called . Whilst internal enrolment is an effective and efficient way of managing course enrolment, particularly if you don&#039;t have a lot of courses, different enrolment&lt;br /&gt;
&lt;br /&gt;
==Manual enrolment==&lt;br /&gt;
&lt;br /&gt;
A user can be [[Assign_roles#Assigning_a_role|manually enrolled]] by [[Assign_roles|assigned a role]] in the course. Administrators and Teachers use this method to assign students or non-editing teachers  from the list of site users to a specific course.&lt;br /&gt;
&lt;br /&gt;
# Click on the &amp;quot;Assign roles&amp;quot; link in the course administration block.&lt;br /&gt;
# Click on student link. &lt;br /&gt;
# Select the user from the list of potential users on the right by clicking on the user.&lt;br /&gt;
##Multiple users may be selected by holding down the Apple or Ctrl key whilst clicking on the users&#039; names.&lt;br /&gt;
# Use the left-facing arrow button to add the selected user to the list of existing users on the left.&lt;br /&gt;
[[Image:Roles Assign Student.JPG|thumb|center|Example of assigning users to a student role]]&lt;br /&gt;
&lt;br /&gt;
==Enrolment plugins==&lt;br /&gt;
Enrolment plugins automate the enrolment process. Please see [[Enrolment plugins]] for more information.  In general, they can use batch files or receive a verification outside of the course context, to enrol a student in a course. For example:&lt;br /&gt;
 &lt;br /&gt;
*There maybe a charge for a course and a student can be automatically enrolled after paying the required fee.  &lt;br /&gt;
*The school has one non_Moodle database maintained by the registrar and the business office for enrolment of both on-line and classroom students.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
*[[Enrolment FAQ]]&lt;br /&gt;
*[[Unenrolment]]&lt;br /&gt;
*[[Enrolment plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Enrolment]]&lt;br /&gt;
&lt;br /&gt;
[[de:Kurseinschreibung]]&lt;/div&gt;</summary>
		<author><name>Azoltay</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/30/en/index.php?title=MNet&amp;diff=80933</id>
		<title>MNet</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/index.php?title=MNet&amp;diff=80933"/>
		<updated>2011-01-28T17:38:45Z</updated>

		<summary type="html">&lt;p&gt;Azoltay: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The network feature allows a Moodle administrator to establish a link with another Moodle, and to share some resources with the users of that Moodle. This features was introduced in Moodle 1.8.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The initial release of MNet is bundled with a Authentication Plugin, which makes single-sign-on between Moodles possible. A user with the username &amp;lt;em&amp;gt;jody&amp;lt;/em&amp;gt; logs in to her Moodle server as normal, and clicks on a link that takes her to a page on another Moodle server. Normally, she would have only the privileges of a guest on the remote Moodle, but behind the scenes, single-sign-on has established a fully authenticated session for Jody on the remote site.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039;  MNet requires the use of &#039;&#039;&#039;xmlrpc&#039;&#039;&#039;. Please go to your phpinfo page if you are interested in using this and search for --with-xmlrpc.  If your php has not been compiled with xmlrpc then you need to address that first! At present it appears that PEAR xmlrpc will not work.&lt;br /&gt;
[[Image:Administration Block Users Authentication MoodleNetwork.jpg|thumb|MNet setting in &#039;&#039;Admin &amp;gt; User &amp;gt; Authentication &amp;gt; Moodle Network]]&lt;br /&gt;
&lt;br /&gt;
==Security==&lt;br /&gt;
The MNet feature requires that your server has the &#039;&#039;&#039;Curl&#039;&#039;&#039; and &#039;&#039;&#039;OpenSSL&#039;&#039;&#039; extensions installed. When you install or upgrade to Moodle 1.8, your system will generate a new OpenSSL certificate for encrypted communication with other Moodles, and will thereafter rotate encryption keys on a monthly basis (approx).&lt;br /&gt;
&lt;br /&gt;
Communication takes place over an XML-RPC transport, and the XML-RPC documents are wrapped first in an XMLDSIG (XML digital signature) envelope, and then in an XMLENC (XML encryption) envelope. The encryption all happens within PHP, and does not require an https (Apache SSL) server.&lt;br /&gt;
&lt;br /&gt;
References:&lt;br /&gt;
*[http://www.w3.org/TR/xmldsig-core/ XML Digital Signatures]&lt;br /&gt;
*[http://www.w3.org/TR/xmlenc-core/ XML Encryption]&lt;br /&gt;
&lt;br /&gt;
A special mode can be enabled which would allow a machine with a specified IP address to make calls to the XML-RPC layer without using either encryption or signature envelopes. This mode is provided to enable Moodle to communicate with other software systems in which the integration of signatures and encryption might be prohibitively difficult. It is not envisioned that unencrypted inter-Moodle networking will ever be enabled.&lt;br /&gt;
&lt;br /&gt;
==Peer to Peer Network==&lt;br /&gt;
&lt;br /&gt;
This is the basic layout of the system. It can be very useful to run one Moodle per faculty or departments, each with its own user management, and yet permit users to roam across the Moodle installs... subject to permissions of course. &lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
&lt;br /&gt;
The instructions will cover 2 Moodle installations: MoodleA and MoodleB. Both are installed correctly and have never had a Moodle Network configuration.&lt;br /&gt;
&lt;br /&gt;
Note: If you experience problems, ensure debugging is turned on in &#039;&#039;Site Administration &amp;gt; Server &amp;gt; Debugging&#039;&#039;. Extra diagnostic messages may be displayed (particularly from Moodle 1.9.2)&lt;br /&gt;
&lt;br /&gt;
For Moodle 2.0, you need to enable Networking (under the Site Administration &amp;gt; Advanced Features menu). This will add the &amp;quot;Networking&amp;quot; menu to the Site Administration menu.&lt;br /&gt;
&lt;br /&gt;
# Get them to talk to each other&lt;br /&gt;
## Ensure &#039;&#039;Admin &amp;gt; Server &amp;gt; Environment&#039;&#039; indicates you have curl installed&lt;br /&gt;
## If MoodleA and MoodleB are hosted in the same domain, ensure they have a different cookie prefix. Note that changing the cookie prefix will log you out! You can change the cookie prefix via &#039;&#039;Admin &amp;gt; Server &amp;gt; Session Handling&#039;&#039;.&lt;br /&gt;
## On both, go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Settings&#039;&#039; and turn Networking ON.&lt;br /&gt;
## On MoodleA go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Peers&#039;&#039; - put the URL of MoodleB under &amp;quot;Add New Host&amp;quot; and click Add. The URL should include the directory where your Moodle code is located, for example &#039;&#039;www.mymoodle.org/moodle&#039;&#039;.&lt;br /&gt;
## Do the equivalent on MoodleB.&lt;br /&gt;
# Get user roaming going&lt;br /&gt;
## (skip this step for moodle 2.0 sites [http://moodle.org/mod/forum/discuss.php?d=141491] ) &#039;&#039; On both, go to &#039;&#039;Administration &amp;gt; Plugins &amp;gt; Authentication &amp;gt; Manage authentication&#039;&#039; in 2.0 onwards or &#039;&#039;Administration &amp;gt; Users &amp;gt; Authentication &amp;gt; Manage authentication&#039;&#039; in 1.9 and enable Moodle Network authentication plugin. Click on &#039;Settings&#039; and enable auto_add_remote_users.&#039;&#039;&lt;br /&gt;
## On MoodleA go to &#039;&#039;Admin &amp;gt; Networking &amp;gt; (Manage) Peers&#039;&#039;, click on &#039;MoodleB&#039;, and click on &#039;Services&#039;. Enable SSO-IDP publish and subscribe, and SSO-SP publish and subscribe.&lt;br /&gt;
## Do the equivalent on MoodleB.&lt;br /&gt;
## On both, go to &#039;&#039;Admin &amp;gt; Users &amp;gt; Permissions &amp;gt; Define Roles&#039;&#039;, only roles that have &amp;quot;Roam to a remote Moodle moodle/site:mnetlogintoremote&amp;quot; will be allowed to roam. Grant the privilege as appropriate.&lt;br /&gt;
## On both, go to the homepage, and add the &#039;Network Servers&#039; block.&lt;br /&gt;
## To test, it is recommended to use a different browser (even on a different machine) that is logged in to neither. Login to MoodleA with a non-administrator account that has the permissions to roam. You should see the Network Servers block, and clicking on it you should go to MoodleB with a newly autocreated account. &lt;br /&gt;
# Get remote enrolments going -- this is optional. It allows an administrator of MoodleB to enrol users that are &amp;quot;native&amp;quot; to MoodleB in remote courses in MoodleA, and viceversa.&lt;br /&gt;
## On both, go to &#039;&#039;Site administration &amp;gt; Plugins &amp;gt; Enrolments &amp;gt; Manage enrol plugins&#039;&#039; in 2.0 onwards or &#039;&#039;Administration &amp;gt; Courses &amp;gt; Enrolments&#039;&#039; pre-2.0 and enable Moodle Network enrolment plugin (click Save). Click on &#039;Edit&#039; and enable &#039;allow_allcourses&#039; or select some courses or categories to be remotely enrolled.&lt;br /&gt;
## On MoodleA go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Peers&#039;&#039;, click on &#039;MoodleB&#039;, and click on &#039;Services&#039;. Enable Enrolment publish and subscribe.&lt;br /&gt;
## Do the equivalent on MoodleB.&lt;br /&gt;
## To use, in MoodleA go to &#039;&#039;Admin &amp;gt; Networking &amp;gt; Enrolments&#039;&#039;. You will see MoodleB listed. Click on MoodleB and you will see a list of courses that MoodleB offers for remote enrolment. Select the course you want, and then enroll the users you want to that course.&lt;br /&gt;
&lt;br /&gt;
===Using it===&lt;br /&gt;
&lt;br /&gt;
==Connecting to a Mnet hub==&lt;br /&gt;
A Mnet hub (do not confuse it with the [[Community hub]] project of Moodle 2.0) is a Moodle server that is configured to accept connections from other Moodle servers, and to provide a set of services to users of these other servers. This guideline will direct you to connect to a Mnet hub, assess the services it has to offer, and enable those services for your users.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
# Get talking to the Hub&lt;br /&gt;
## Ensure that the &#039;&#039;Admin &amp;gt; Server &amp;gt; Environment&#039;&#039; page indicates you have curl and openssl installed&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Settings&#039;&#039; and turn Networking on&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Peers&#039;&#039; and enter the URL of Mnet Hub under &amp;quot;Add New Host&amp;quot;. Click &amp;lt;em&amp;gt;Add&amp;lt;/em&amp;gt;&lt;br /&gt;
## The host details for the Mnet Hub should appear with the Site Name field already populated. Click &amp;lt;em&amp;gt;Save changes&amp;lt;/em&amp;gt;&lt;br /&gt;
## The details will be written to your database and two new tabs will appear in this window: &#039;Services&#039; and &#039;Logs&#039;. Click &amp;lt;em&amp;gt;Services&amp;lt;/em&amp;gt;&lt;br /&gt;
##A list of services will appear, each with a checkbox for &#039;publish&#039; and &#039;subscribe&#039;. Check the checkboxes for any services you want to publish or subscribe to&lt;br /&gt;
&lt;br /&gt;
===Using it===&lt;br /&gt;
If the Mnet Hub has already enabled a service for you, there will be a tick alongside the appropriate checkbox, for example: if the Hub is &amp;lt;em&amp;gt;publishing&amp;lt;/em&amp;gt; Moodle Networked Enrolment, then a tick will appear alongside the &amp;lt;em&amp;gt;subscribe&amp;lt;/em&amp;gt; checkbox for this service. Note that in order to enable some functionality, prominently &amp;lt;em&amp;gt;single-sign-on&amp;lt;/em&amp;gt;, you may have to &amp;lt;em&amp;gt;publish&amp;lt;/em&amp;gt; a service, e.g. the &amp;lt;em&amp;gt;Identity Provider&amp;lt;/em&amp;gt; service. The Mnet Hub will access this service on your Moodle, asking it to authenticate your users.&lt;br /&gt;
# Enable Roaming&lt;br /&gt;
## Subscribe to &amp;lt;em&amp;gt;SSO (Service Provider)&amp;lt;/em&amp;gt; by checking the box&lt;br /&gt;
## Publish &amp;lt;em&amp;gt;SSO (Identity Provider)&amp;lt;/em&amp;gt; by checking the box&lt;br /&gt;
## Click &amp;lt;em&amp;gt;Save changes&amp;lt;/em&amp;gt;&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Users &amp;gt; Permissions &amp;gt; Define Roles&#039;&#039;, and grant the capability &amp;lt;em&amp;gt;Roam to a remote Moodle moodle/site:mnetlogintoremote&amp;lt;/em&amp;gt; to an appropriate role&lt;br /&gt;
## Go to &#039;&#039;Administration &amp;gt; Plugins &amp;gt; Authentication &amp;gt; Manage authentication&#039;&#039; in 2.0 onwards or &#039;&#039;Administration &amp;gt; Users &amp;gt; Authentication &amp;gt; Manage authentication&#039;&#039; in 1.9 and enable the &amp;lt;em&amp;gt;Moodle Network authentication&amp;lt;/em&amp;gt; plugin&lt;br /&gt;
## Go to your homepage, turn on editing, and add the &#039;Network Servers&#039; block&lt;br /&gt;
## Using a different web-browser, log on as a non-admin user who inhabits the role you granted the roaming capability to&lt;br /&gt;
## Note that the Mnet Hub is listed in the Network Servers block on the homepage. Click on the link to that server&lt;br /&gt;
## Some of your user details will be transferred to the Mnet Hub server, and a browsing session will be started for you as if you had logged on there directly&lt;br /&gt;
# Enable Networked Enrolment&lt;br /&gt;
## Return to the web browser you&#039;ve been using as the site administrator&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Peers&#039;&#039; and click on the entry for the Mnet Hub.&lt;br /&gt;
## Click on the Services tab&lt;br /&gt;
## Subscribe to &amp;lt;em&amp;gt;Moodle Networked Enrolment&amp;lt;/em&amp;gt;&lt;br /&gt;
## Go to &#039;&#039;Site administration &amp;gt; Plugins &amp;gt; Enrolments &amp;gt; Manage enrol plugins&#039;&#039; in 2.0 onwards or &#039;&#039;Administration &amp;gt; Courses &amp;gt; Enrolments&#039;&#039; pre-2.0 and enable the &amp;lt;em&amp;gt;Moodle Network enrolment&amp;lt;/em&amp;gt; plugin. Click &amp;lt;em&amp;gt;Save changes&amp;lt;/em&amp;gt;&lt;br /&gt;
## Click on &amp;lt;em&amp;gt;edit&amp;lt;/em&amp;gt; to view the details for networked enrolments.&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Networking &amp;gt; Enrolments&#039;&#039; to see a list of Moodle servers that offer this service to you&lt;br /&gt;
## Click on a server name to view a list of courses that the server offers to your users&lt;br /&gt;
## Click on a course name, to view a list users that you can enrol in this course&lt;br /&gt;
## Enrol users&lt;br /&gt;
## Profit!&lt;br /&gt;
&lt;br /&gt;
==Running a Mnet hub==&lt;br /&gt;
A Mnet hub is a regular Moodle site that runs in a special mode. As a Moodle Administrator, when you add another Moodle site to your list of network peers, your Moodle will contact that site to find out what it is called, and to request its public key for encrypted communication. Normally, the remote server will simply provide this information without making any record of the transaction.&lt;br /&gt;
&lt;br /&gt;
A Mnet hub is different. As soon as you add an entry for a Mnet hub to your system, the Mnet hub will create an entry for your server in its list of hosts, and may immediately begin to offer services to the users of your site.&lt;br /&gt;
&lt;br /&gt;
This section will guide you to set up a Mnet hub, and select services to offer to all comers.&lt;br /&gt;
&lt;br /&gt;
===Setup===&lt;br /&gt;
# Enable Networking&lt;br /&gt;
## Ensure that the &#039;&#039;Admin &amp;gt; Server &amp;gt; Environment&#039;&#039; page indicates you have curl and openssl installed&lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Settings&#039;&#039; and turn Networking on &lt;br /&gt;
## Go to &#039;&#039;Admin &amp;gt; Network &amp;gt; Peers&#039;&#039; and tick the checkbox for &amp;lt;em&amp;gt;Register all hosts&amp;lt;/em&amp;gt;. Click on &amp;lt;em&amp;gt;Save Changes&amp;lt;/em&amp;gt;&lt;br /&gt;
## On the same page, the first entry in your list of hosts should be &amp;lt;em&amp;gt;All hosts&amp;lt;/em&amp;gt;. Click this link&lt;br /&gt;
## Click on &amp;lt;em&amp;gt;Services&amp;lt;/em&amp;gt; and enable any services you want to offer to all comers&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Moodle Network FAQ]]&lt;br /&gt;
* [[Development:Moodle Network|Moodle Network development notes]]&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/view.php?id=6976 MNet forum]&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/discuss.php?d=92749 Examples of how people are using Moodle networks] forum discussion&lt;br /&gt;
&lt;br /&gt;
[[Category:Authentication]]&lt;br /&gt;
[[Category:Enrolment]]&lt;br /&gt;
[[Category:MNet]]&lt;br /&gt;
&lt;br /&gt;
[[fr:Réseau Moodle]]&lt;br /&gt;
[[ja:Moodleネットワーク]]&lt;br /&gt;
[[es:Red Moodle]]&lt;br /&gt;
[[cs:Síťové služby]]&lt;/div&gt;</summary>
		<author><name>Azoltay</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/30/en/index.php?title=Development:Local_customisation&amp;diff=77442</id>
		<title>Development:Local customisation</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/index.php?title=Development:Local_customisation&amp;diff=77442"/>
		<updated>2010-11-02T22:17:15Z</updated>

		<summary type="html">&lt;p&gt;Azoltay: /* 2.0 pre-upgrade script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Local customisations&lt;br /&gt;
|state = Implemented&lt;br /&gt;
|tracker = MDL-17376, MDL-16438&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=126017 http://moodle.org/mod/forum/discuss.php?d=86903&lt;br /&gt;
|assignee = [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]], some parts were originally proposed and implemented in 1.9 by Penny Leach&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The recommended way to add new functionality to Moodle is to create a new standard plugin (module, block, auth, enrol, etc.).The /local/ plugins are mostly suitable for things that do not fit standard plugins.&lt;br /&gt;
&lt;br /&gt;
=Custom /local/ plugins=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Local plugins are used in cases when no standard plugin fits, examples are:&lt;br /&gt;
* event consumers communicating with external systems&lt;br /&gt;
* custom definitions of web services and external functions&lt;br /&gt;
* applications that extend moodle at the system level (hub server, amos server, etc.)&lt;br /&gt;
* new database tables used in core hacks (discouraged)&lt;br /&gt;
* new capability definitions used in core hacks&lt;br /&gt;
* custom admin settings&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Standard plugin features:&lt;br /&gt;
* /local/xxx/db/version.php - version of script (must be incremented after changes)&lt;br /&gt;
* /local/xxx/db/install.xml - executed during install (new version.php found)&lt;br /&gt;
* /local/xxx/db/install.php - executed right after install.xml&lt;br /&gt;
* /local/xxx/db/uninstall.php - executed during uninstallation&lt;br /&gt;
* /local/xxx/db/upgrade.php - executed after version.php change&lt;br /&gt;
* /local/xxx/db/access.php - definition of capabilities&lt;br /&gt;
* /local/xxx/db/events.php - event handlers and subscripts&lt;br /&gt;
* /local/xxx/db/messages.php - messaging registration&lt;br /&gt;
* /local/xxx/db/external.php - web services and external functions descriptions&lt;br /&gt;
* /local/xxx/lang/en/local_pluginname.php - language file&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;xxx&#039;&#039; is used instead of your local plugin name, plugins of the same type are installed/upgraded in alphabetical order.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
List of differences from normal plugins:&lt;br /&gt;
* always executed last during install/upgrade - guaranteed by order of plugins in &amp;lt;code&amp;gt;get_plugin_types()&amp;lt;/code&amp;gt;&lt;br /&gt;
* are expected to use event handlers - events are intended for communication core--&amp;gt;plugins only, local plugins are the best candidates for event handlers&lt;br /&gt;
* can add admin settings to any settings page - loaded last when constructing admin tree&lt;br /&gt;
* do not need to have any UI - other plugins are usually visible somewhere&lt;br /&gt;
* some extra hooks (not implemented yet)&lt;br /&gt;
&lt;br /&gt;
=Other /local/ customisation files=&lt;br /&gt;
&lt;br /&gt;
==Customised site defaults==&lt;br /&gt;
&lt;br /&gt;
Different default site settings can be stored in file /local/defaults.php.&lt;br /&gt;
These new defaults are used during installation, upgrade and later are&lt;br /&gt;
displayed as default values in admin settings. This means that the content&lt;br /&gt;
of the defaults files is usually updated BEFORE installation or upgrade.&lt;br /&gt;
&lt;br /&gt;
These customised defaults are useful especially when using CLI tools&lt;br /&gt;
for installation and upgrade.&lt;br /&gt;
&lt;br /&gt;
Sample /local/defaults.php file content:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$defaults[&#039;moodle&#039;][&#039;forcelogin&#039;] = 1;  // new default for $CFG-&amp;gt;forcelogin&lt;br /&gt;
$defaults[&#039;scorm&#039;][&#039;maxgrade&#039;] = 20;    // default for get_config(&#039;scorm&#039;, &#039;maxgrade&#039;)&lt;br /&gt;
$defaults[&#039;moodlecourse&#039;][&#039;numsections&#039;] = 11;&lt;br /&gt;
$defaults[&#039;moodle&#039;][&#039;hiddenuserfields&#039;] = array(&#039;city&#039;, &#039;country&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
First bracket contains string from column plugin of config_plugins table.&lt;br /&gt;
Second bracket is the name of setting. In the admin settings UI the plugin and&lt;br /&gt;
name of setting is separated by &amp;quot;|&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The values usually correspond to the raw string in config table, with the exception&lt;br /&gt;
of comma separated lists that are usually entered as real arrays.&lt;br /&gt;
&lt;br /&gt;
Please note that not all settings are converted to admin_tree,&lt;br /&gt;
they are mostly intended to be set directly in config.php.&lt;br /&gt;
&lt;br /&gt;
==2.0 pre-upgrade script==&lt;br /&gt;
&lt;br /&gt;
You can use /local/upgrade_pre20.php script for any code that needs to&lt;br /&gt;
be executed before the main upgrade to 2.0. Most probably this will&lt;br /&gt;
be used for undoing of old hacks that would otherwise break normal&lt;br /&gt;
2.0 upgrade.&lt;br /&gt;
&lt;br /&gt;
This file is just included directly, there does not need to be any&lt;br /&gt;
function inside. If the execution stops the script is executed again&lt;br /&gt;
during the next upgrade. The first execution of lib/db/upgrade.php&lt;br /&gt;
increments the version number and the pre upgrade script is not&lt;br /&gt;
executed any more.&lt;br /&gt;
&lt;br /&gt;
=Customisations outside of /local/ directory=&lt;br /&gt;
&lt;br /&gt;
==Forced settings==&lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force some settings and prevent any changes of these settings via the standard admin UI. It is possible to hardcode these settings in config.php.&lt;br /&gt;
&lt;br /&gt;
In case of course settings it is very simply, the values are assigned directly to $CFG properties. In case of plugins the values are specified in a multidimensional array in $CFG-&amp;gt;force_plugin_settings.&lt;br /&gt;
&lt;br /&gt;
Sample code in config.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;allowobjectembed = 0;&lt;br /&gt;
$CFG-&amp;gt;forced_plugin_settings = array(&#039;page&#039;=&amp;gt;array(&#039;displayoptions&#039;=&amp;gt;5, &#039;requiremodintro&#039;=&amp;gt;1), &#039;folder&#039;=&amp;gt;&#039;requiremodintro&#039;=&amp;gt;1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Local language customisations==&lt;br /&gt;
&lt;br /&gt;
Moodle supports other type of local customisation of standard language&lt;br /&gt;
packs. If you want to create your own language pack based on another&lt;br /&gt;
language create new dataroot directory with &amp;quot;_local&amp;quot; suffix, for example&lt;br /&gt;
following file with content changes string &amp;quot;Login&amp;quot; to &amp;quot;Sign in&amp;quot;:&lt;br /&gt;
moodledata/lang/en_local&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
  $string[&#039;login&#039;] = &#039;Sign in&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See also https://docs.moodle.org/en/Language_editing&lt;br /&gt;
&lt;br /&gt;
==Custom script injection==&lt;br /&gt;
&lt;br /&gt;
Very old customisation option that allows you to modify scripts by injecting&lt;br /&gt;
code right after the require &#039;config.php&#039; call.&lt;br /&gt;
&lt;br /&gt;
This setting is enabled by manually setting $CFG-&amp;gt;customscripts variable&lt;br /&gt;
in config.php script. The value is expected to be full path to directory&lt;br /&gt;
with the same structure as dirroot. Please note this hack only affects&lt;br /&gt;
files that actually include the config.php!&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* disable one specific moodle page without code modification&lt;br /&gt;
* alter page parameters on the fly&lt;br /&gt;
&lt;br /&gt;
==Direct code modifications==&lt;br /&gt;
This is usually the last resort, if possible do not do it. And if you still do it use some version control system (preferably git).&lt;br /&gt;
&lt;br /&gt;
==Direct database modifications==&lt;br /&gt;
Very strongly discouraged! Sometimes field lengths may be modified without side effects. Adding or removing of db fields will most probably cause major problems during future upgrades. New database tables should be added only from plugins.&lt;br /&gt;
&lt;br /&gt;
=Local customisations in previous versions=&lt;br /&gt;
Previous versions include only partial support for customisations in /local/ directory.&lt;br /&gt;
&lt;br /&gt;
List of local customisations in 1.9.x:&lt;br /&gt;
* /local/cron.php - custom cron jobs&lt;br /&gt;
* /local/settings.php - custom admin settings&lt;br /&gt;
* /local/db/upgrade.php - general modifications&lt;br /&gt;
* /local/lang/* - custom strings&lt;br /&gt;
* /local/lib.php - local_delete_course()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Migration from old 1.9.x /local/:&lt;br /&gt;
* &amp;lt;code&amp;gt;local/*&amp;lt;/code&amp;gt; needs to be copied to new directory&lt;br /&gt;
* &amp;lt;code&amp;gt;local/xxxx/db/install.php&amp;lt;/code&amp;gt; is intended for first installation, originally everything was in upgrade.php&lt;br /&gt;
* events are used instead of hooks&lt;br /&gt;
* upgrade code needs to migrate old settings, events, etc. directly in core db tables - such as change component strings and capability names from db/install.php or manually before/after upgrade&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/discuss.php?d=86903 Local Customisations] forum discussion&lt;br /&gt;
* http://cvs.moodle.org/moodle/local/readme.txt?view=markup&lt;br /&gt;
* [[Local customisation (Moodle 1.9)]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer|Local customisation]]&lt;/div&gt;</summary>
		<author><name>Azoltay</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/30/en/index.php?title=Development:Unit_tests&amp;diff=67441</id>
		<title>Development:Unit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/index.php?title=Development:Unit_tests&amp;diff=67441"/>
		<updated>2010-01-21T00:32:16Z</updated>

		<summary type="html">&lt;p&gt;Azoltay: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 1.7}}Location: &#039;&#039;Administration &amp;gt; Reports &amp;gt; Unit tests&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The purpose of Unit Tests is to evaluate the individual parts of a program (functions, and methods of classes) to make sure that each element individually does the right thing. Unit Tests can be one of the first steps in a quality control process for developing or tweaking Moodle code.  The next steps will involve other forms of testing to ensure that these different parts work together properly. &lt;br /&gt;
&lt;br /&gt;
The unit testing framework is based on the [http://www.simpletest.org/ SimpleTest] framework.&lt;br /&gt;
&lt;br /&gt;
== Running the unit tests in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Running the basic tests ===&lt;br /&gt;
&lt;br /&gt;
# Log in with an admin account. &lt;br /&gt;
# Administration ► Development ► Unit tests (moodle &amp;gt;= 2.0, Administration ► Reports ► Unit tests Moodle &amp;lt;= 1.9)&lt;br /&gt;
# Click on the &#039;&#039;&#039;Reports&#039;&#039;&#039; link near the bottom of the page.&lt;br /&gt;
# Click the &#039;&#039;&#039;Run tests&#039;&#039;&#039; button and wait.&lt;br /&gt;
&lt;br /&gt;
This finds all the tests in Moodle and runs them. You can run a subset of the tests by entering a path (for example question/type) in the &#039;Only run tests in&#039; box. Similarly, if a test fails, you get some links in the failure message to make it easy to re-run just those tests.&lt;br /&gt;
&lt;br /&gt;
== Writing new tests ==&lt;br /&gt;
&lt;br /&gt;
As an example, suppose we wanted to write some tests for the string_manager class in mod/quiz/editlib.php.&lt;br /&gt;
&lt;br /&gt;
=== Where to put the tests ===&lt;br /&gt;
&lt;br /&gt;
The unit test report finds tests by looking for files called &#039;test....php&#039; inside folders called &#039;simpletest&#039;.&lt;br /&gt;
&lt;br /&gt;
So, for our example, we want to create called something like &#039;&#039;&#039;mod/quiz/simpletest/testeditlib.php&#039;&#039;&#039;. The skeleton of this file should look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for (some of) mod/quiz/editlib.php.&lt;br /&gt;
 *&lt;br /&gt;
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License&lt;br /&gt;
 * @package question&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
if (!defined(&#039;MOODLE_INTERNAL&#039;)) {&lt;br /&gt;
    die(&#039;Direct access to this script is forbidden.&#039;); //  It must be included from a Moodle page&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Make sure the code being tested is accessible.&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot . &#039;/mod/quiz/editlib.php&#039;); // Include the code to test&lt;br /&gt;
&lt;br /&gt;
/** This class contains the test cases for the functions in editlib.php. */&lt;br /&gt;
class quiz_editlib_test extends UnitTestCase {&lt;br /&gt;
    function test_something() {&lt;br /&gt;
        // Do the test here.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ... more test methods.&lt;br /&gt;
}&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is, you have a class called something_test, and in that class you have lots of methods called test_something. Normally, you have one test method for each particular thing you want to test, and you should try to name the function to describe what is being tested - without making the name too ridiculously long!&lt;br /&gt;
&lt;br /&gt;
=== A test function ===&lt;br /&gt;
&lt;br /&gt;
The a test function typically looks like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function test_move_question_up() {&lt;br /&gt;
    // Setup fixture&lt;br /&gt;
&lt;br /&gt;
    // Exercise SUT&lt;br /&gt;
    $newlayout = quiz_move_question_up(&#039;1,2,0&#039;, 2);&lt;br /&gt;
&lt;br /&gt;
    // Validate outcome&lt;br /&gt;
    $this-&amp;gt;assertEqual($newlayout, &#039;2,1,0&#039;);&lt;br /&gt;
&lt;br /&gt;
    // Teardown fixture&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the [http://xunitpatterns.com/Four%20Phase%20Test.html four phase test pattern]. Those comments use a lot of testing jargon. The fixture is the background situation that needs to be set up before the test runs. SUT is short for &#039;situation under test&#039;. This is where you call the function or method that you want to test. Then you check to see if the function did the right thing. Finally, you have to clean up the fixture you created. With luck there is nothing to do here&lt;br /&gt;
&lt;br /&gt;
In this simple example, there is no setup or teardown to do. We just call the function we are testing with some sample input, and check that the return value is what we expect.&lt;br /&gt;
&lt;br /&gt;
=== Shared setUp and tearDown methods ===&lt;br /&gt;
&lt;br /&gt;
If all your test cases relate to the same area of code, then they may all need to same bit of fixture set up. For example, all the tests in lib/simpletest/teststringmanager.php need an instance of the string_manager class to test.&lt;br /&gt;
&lt;br /&gt;
To avoid duplicating code, you can override a method called &amp;lt;code&amp;gt;setUp()&amp;lt;/code&amp;gt; that sets up the test data. If present, this method will be called before each test method. You can write a matching &amp;lt;code&amp;gt;tearDown()&amp;lt;/code&amp;gt; method if there is any clean-up that needs to be done after each test case has run. For example, in lib/simpletest/teststringmanager.php there are setUp and tearDown methods that do something like:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function setUp() {&lt;br /&gt;
    // ...&lt;br /&gt;
    $this-&amp;gt;stringmanager = new string_manager(...);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public function tearDown() {&lt;br /&gt;
    $this-&amp;gt;stringmanager = null;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then, each test can use $this-&amp;gt;stringmanager without having to worry about the details of how it is set up.&lt;br /&gt;
&lt;br /&gt;
=== Further information ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;SimpleTest&#039;&#039; documentation is at: http://www.simpletest.org/.&lt;br /&gt;
&lt;br /&gt;
== Changes to your existing code to make it work with unit testing ==&lt;br /&gt;
&lt;br /&gt;
The whole point of unit testing is to test each piece of functionality separately. You can only do this is by isolating that function and call it individually, perhaps after setting up a few other things.&lt;br /&gt;
&lt;br /&gt;
Therefore, it is good if you can write your code to depend on as few other things as possible. &lt;br /&gt;
&lt;br /&gt;
=== Include paths ===&lt;br /&gt;
&lt;br /&gt;
Includes like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;); // Won&#039;t work.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
won&#039;t work. Instead, the more robust option is &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(dirname(__FILE__) . &#039;/../../config.php&#039;); // Do this.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access to global variables ===&lt;br /&gt;
&lt;br /&gt;
Because your code was included from within a function, you can&#039;t access global variables until you have done a global statement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(dirname(__FILE__) . &#039;/../../config.php&#039;);&lt;br /&gt;
require_once($CFG-&amp;gt;libdir . &#039;/moodlelib.php&#039;); // Won&#039;t work.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(dirname(__FILE__) . &#039;/../../config.php&#039;);&lt;br /&gt;
&lt;br /&gt;
global $CFG; // You need this.&lt;br /&gt;
require_once($CFG-&amp;gt;libdir . &#039;/moodlelib.php&#039;); // Will work now.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calls to global functions ===&lt;br /&gt;
Testing a class method that calls global functions can be problematic. At least, it&#039;s always complex, because we can&#039;t control what goes on in the global functions. We can&#039;t override the global functions or mock them in our unit tests. If the global functions themselves are well tested, this may not be a big problem, but most global functions are not well tested.&lt;br /&gt;
&lt;br /&gt;
==== Bridge Pattern ====&lt;br /&gt;
If your code needs to rely extensively on some public API, you could use the [http://en.wikipedia.org/wiki/Bridge_pattern bridge pattern] to decouple your code from that API. This way, when you write unit tests, you can override the bridging class or mock it, and control its outputs while you focus exclusively on testing your code.&lt;br /&gt;
&lt;br /&gt;
An basic example follows: Imagine that I do not trust the &#039;&#039;get_string()&#039;&#039; global function, but my code needs to use it. Initially my code has strong coupling with &#039;&#039;get_string()&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class myclass {&lt;br /&gt;
    public function print_stuff($stuff) {&lt;br /&gt;
        echo get_string($stuff);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s write a bridging class to solve this coupling issue and use it instead of &#039;&#039;get_string()&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class languageBridge {&lt;br /&gt;
    public function get_string($stuff,$module=&#039;moodle&#039;) {&lt;br /&gt;
        echo get_string($stuff, $module);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class myclass {&lt;br /&gt;
    public $lang_bridge;&lt;br /&gt;
    public function __construct() {&lt;br /&gt;
        $this-&amp;gt;lang_bridge = new languageBridge();&lt;br /&gt;
    }&lt;br /&gt;
    public function print_stuff($stuff) {&lt;br /&gt;
        echo $this-&amp;gt;lang_bridge-&amp;gt;get_string($stuff);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following is yet another example using a bridging method to decouple from the Moodle core API.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class workshop_api {&lt;br /&gt;
    /**&lt;br /&gt;
     * This is a method we want to unittest&lt;br /&gt;
     */&lt;br /&gt;
    public function get_peer_reviewers($context) {&lt;br /&gt;
        static $users=null;&lt;br /&gt;
        if (is_null($users)) {&lt;br /&gt;
            $users = $this-&amp;gt;get_users_by_capability($context, &#039;mod/workshop:peerassess&#039;, &lt;br /&gt;
                        &#039;u.id, u.lastname, u.firstname&#039;, &#039;u.lastname,u.firstname&#039;, &#039;&#039;, &#039;&#039;, &#039;&#039;, &#039;&#039;, false, false, true);&lt;br /&gt;
        }&lt;br /&gt;
        return $users;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**  &lt;br /&gt;
     * Bridging method to decouple from Moodle core API&lt;br /&gt;
     */&lt;br /&gt;
    protected function get_users_by_capability() {&lt;br /&gt;
        $args = func_get_args();&lt;br /&gt;
        return call_user_func_array(&#039;get_users_by_capability&#039;, $args);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning:&#039;&#039;&#039; Here are some comments on the examples above expressing that the bridge pattern should be used very carefully.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;I think that is a case of unit tests leading to worse software design, in that you are not using the standard API for something. But if you really want to unit test, I can&#039;t think of a better solution.&amp;quot;&lt;br /&gt;
* &amp;quot;I think this can be OK if used very selectively. Unfortunately I don&#039;t think it&#039;s the solution if you want to decouple the very complex and deeply nested Moodle functions from each other&amp;quot;&lt;br /&gt;
* &amp;quot;...your code is designed to be part of Moodle, so decoupling from a standard Moodle API is perverse.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Unit testing in 2.0 ==&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
With the Objectification of the Database libraries in Moodle 2.0, new and better approaches to Unit testing can be used. Here is a sample of a simple test case: (in course/simpletest)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 require_once($CFG-&amp;gt;dirroot . &#039;/course/lib.php&#039;);&lt;br /&gt;
 &lt;br /&gt;
 global $DB;&lt;br /&gt;
 Mock::generate(get_class($DB), &#039;mockDB&#039;);&lt;br /&gt;
 &lt;br /&gt;
 class courselib_test extends UnitTestCase {&lt;br /&gt;
     var $realDB;&lt;br /&gt;
 &lt;br /&gt;
     function setUp() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;realDB = $DB;&lt;br /&gt;
         $DB           = new mockDB();&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     function tearDown() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $DB = $this-&amp;gt;realDB;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     function testMoveSection() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $course = new stdClass();&lt;br /&gt;
         $course-&amp;gt;id = 1;&lt;br /&gt;
 &lt;br /&gt;
         $sections = array();&lt;br /&gt;
         for ($i = 1; $i &amp;lt; 11; $i++) {&lt;br /&gt;
             $sections[$i]          = new stdClass();&lt;br /&gt;
             $sections[$i]-&amp;gt;id      = $i;&lt;br /&gt;
             $sections[$i]-&amp;gt;section = $i - 1;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         $DB-&amp;gt;expectOnce(&#039;get_records&#039;, array(&#039;course_sections&#039;, array(&#039;course&#039; =&amp;gt; $course-&amp;gt;id)));&lt;br /&gt;
         $DB-&amp;gt;setReturnValue(&#039;get_records&#039;, $sections);&lt;br /&gt;
         $this-&amp;gt;assertFalse(move_section($course, 2, 3));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also &#039;&#039;&#039;UnitTestCaseUsingDatabase&#039;&#039;&#039; in lib/simpletestlib.php.&lt;br /&gt;
&lt;br /&gt;
=== Testing HTML output ===&lt;br /&gt;
&lt;br /&gt;
(work in progress - to be documented properly once the API stabilizes)&lt;br /&gt;
&lt;br /&gt;
* ContainsTagWithAttribute($tag, $attribute, $value)&lt;br /&gt;
* ContainsTagWithAttributes($tag, $attributes)&lt;br /&gt;
* ContainsTagWithContents($tag, $content)&lt;br /&gt;
* ContainsEmptyTag($tag)&lt;br /&gt;
&lt;br /&gt;
The syntax is &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;assert(new ContainsTagWithAttribute($tag, $attribute, $value), $html);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code coverage analysis==&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039; This section is a work in progress. Please use the [[{{TALKPAGENAME}}|page comments]] or an appropriate [http://moodle.org/course/view.php?id=5 moodle.org forum] for any recommendations/suggestions for improvement.{{{info|}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Wikipedia:Code_coverage|Code coverage]]&#039;&#039;&#039; is a technique, strongly tied with software testing, that allows to &#039;&#039;&#039;check and improve the quality of the tests&#039;&#039;&#039; by measuring the degree of source code that is being covered by them. With Moodle supporting more and more tests each day (slowly towards a &#039;&#039;&#039;Test Driven Development&#039;&#039;&#039; model) we need to integrate some tool into our development process helping to analyse the quality of ours tests.&lt;br /&gt;
&lt;br /&gt;
Right now (in Moodle 2.0) we are using [http://www.simpletest.org/ SimpleTest], one simple and great tool to perform all the tests. Unluckily, it doesn&#039;t support code coverage analysis at all. In the other hand, other PHP unit testing products like [http://www.phpunit.de/ PHPUnit], more complex and powerful, have built-in support for that technique, but switching to a new product is out from our current [[Roadmap]] plans.&lt;br /&gt;
&lt;br /&gt;
So, after some readings and comparisons, Moodle will implement its own extensions to SimpleTest, in order to fulfil the main goal of having statement/line code coverage analysis working under Moodle 2.0 onwards. To achieve this, also [http://developer.spikesource.com/projects/phpcoverage Spike PHPCoverage], a basic code-coverage tool, will be used and extended. You can find the details of the implementation of this tool at MDL-19579.&lt;br /&gt;
&lt;br /&gt;
=== Changes ===&lt;br /&gt;
&lt;br /&gt;
To enable code coverage in your tests, only a few modifications need to be performed to your current code:&lt;br /&gt;
&lt;br /&gt;
# Change your test classes by adding two (public static) attributes: &#039;&#039;&#039;$includecoverage&#039;&#039;&#039; and &#039;&#039;&#039;$excludecoverage&#039;&#039;&#039;, both arrays, being used to inform to the code coverage tool (via reflection) about which source code files and dirs must be covered/skipped by the analysis.&lt;br /&gt;
# Use &#039;&#039;&#039;[http://cvs.moodle.org/moodle/lib/simpletestcoveragelib.php?view=markup simpletestcoveragelib.php]&#039;&#039;&#039; instead of simpletestlib.php in your caller scripts.&lt;br /&gt;
# Use the &#039;&#039;&#039;autogroup_test_coverage&#039;&#039;&#039; class instead of the AutoGroupTest one (see below for details) in your caller scripts.&lt;br /&gt;
&lt;br /&gt;
(note that only the 1st point above is needed for new unit tests being created because both 2 and 3 (changes in caller scripts) are already implemented in Moodle and awaiting your cool unit tests.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all! With those 3 basic changes, you will end with a complete code coverage report available for further analysis.&lt;br /&gt;
&lt;br /&gt;
=== API ===&lt;br /&gt;
&lt;br /&gt;
When using code coverage within Moodle there are two alternative APIs available, both providing the same code coverage reports at the end, but doing that in a different way. Here they are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Internal (hidden) coverage API&#039;&#039;&#039;: This API is completely hidden beyond the Unit testing API and you won&#039;t need to know the details about it. Just perform the 1-2-3 changes described above and, after running the tests you&#039;ll get the final report available for being used immediately, without needing to perform anything in your code. His major drawback: it only can perform &#039;&#039;&#039;one&#039;&#039;&#039; &amp;quot;code coverage session&amp;quot; (a.k.a. instrumentation), so it&#039;s only suitable for testing scripts using only one unit test execution. One example of this type of unit testing is  [http://cvs.moodle.org/moodle/admin/report/unittest/index.php?view=markup admin/report/unittest/index.php] where only one (big) test-group is executed.&lt;br /&gt;
* &#039;&#039;&#039;External (explicit) coverage API&#039;&#039;&#039;: This API needs extra coding as long as coverage instantiating, configuration and report generation happens in the main script. It&#039;s a bit more complex but, in the other hand, it support &#039;&#039;&#039;multiple&#039;&#039;&#039; instrumentations to be performed, and gives you more control about the code coverage process.  One example of this type of unit testing is  [http://cvs.moodle.org/moodle/admin/report/unittest/dbtest.php?view=markup admin/report/unittest/dbtest.php] where multiple (one for each DB being tested) test-group are executed.&lt;br /&gt;
&lt;br /&gt;
So, first of all (point 1 in prev section - usage), we need to define, for each unit test, which files / directories (relative to dirroot) we want to analyse with the tool. Here it&#039;s one example, for the &#039;&#039;&#039;dml_test&#039;&#039;&#039; unit test ([http://cvs.moodle.org/moodle/lib/dml/simpletest/testdml.php?view=markup /lib/dml/simpletest/testdml.php]), all we need to add to these lines to the class declaration :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public  static $includecoverage = array(&#039;lib/dml&#039;);&lt;br /&gt;
public  static $excludecoverage = array(&#039;lib/dml/somedir&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By doing so, the code coverage tool will know which are the target files to perform coverage analysis/reporting and will do that for all the files (recursively) in the &#039;&#039;lib/dml&#039;&#039;&#039; dir but excluding the &#039;&#039;lib/dml/somedir&#039;&#039; directory (recursively too). Note that both attributes are arrays so multiple paths can be specified in any of them. Also note that the dir where the UnitTest is stored is automatically excluded (usually &#039;&#039;simpletest&#039;&#039; dirs).&lt;br /&gt;
&lt;br /&gt;
And, as said, that&#039;s all you need to fulfil in order to get current/new unit tests being analysed by the code coverage tool by current Moodle scripts. The documentation below is only interesting for developers wanting to create new scripts able to perform unit testing with code coverage (points 2 and 3 in prev section - usage).&lt;br /&gt;
&lt;br /&gt;
==== Internal coverage API ====&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test = new autogroup_test_coverage($showsearch, $test_name, $performcoverage, $coveragename, $coveragedir);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Create one new autogroup test object with code coverage support, there you can specify if you want to perform coverage (true/false), the name of the report (title) and the directory where the final report will be created (under moodledata/codecoverage). &lt;br /&gt;
Optionally you can add more files and directories (relative to dirroot) to the list of files to be covered / ignored by using these functions (in case the defined in point 1 aren&#039;t enough).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test-&amp;gt;add_coverage_include_path($path);&lt;br /&gt;
$test-&amp;gt;add_coverage_exclude_path($path);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
And then, affter adding a bunch of unit tests to the group, you simply invoke the test execution with code coverage support to end with a nice code coverage report under &#039;&#039;dataroot/codecoverage/$coveragedir&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test-&amp;gt;run($unit_test_reporter);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(don&#039;t forget that this API supports only &#039;&#039;&#039;one&#039;&#039;&#039; instrumentation to be performed)&lt;br /&gt;
&lt;br /&gt;
And that&#039;s all!&lt;br /&gt;
&lt;br /&gt;
==== External coverage API ====&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$covreporter = new moodle_coverage_reporter($coveragename, $coveragedir);&lt;br /&gt;
$covrecorder = new moodle_coverage_recorder($covreporter);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Create one coverage reporter, by passing its title and output directory as parameters.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test = new autogroup_test_coverage($showsearch, $test_name, $performcoverage);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Create one new autogroup test object with code coverage support, you don&#039;t need to specify the title and dir here (as already have been defined by the moodle_coverage_reporter object).&lt;br /&gt;
Optionally you can add more files and directories (relative to dirroot) to the list of files to be covered / ignored by using these functions (in case the defined in point 1 aren&#039;t enough).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test-&amp;gt;add_coverage_include_path($path);&lt;br /&gt;
$test-&amp;gt;add_coverage_exclude_path($path);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then, after adding a bunch of unit tests to the group, you simply invoke the test execution with code coverage support with:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$test-&amp;gt;run_with_external_coverage($unit_test_reporter, $covrecorder);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(don&#039;t forget that this API supports &#039;&#039;&#039;multiple&#039;&#039;&#039; instrumentations to be performed)&lt;br /&gt;
&lt;br /&gt;
And finally, you generate the code coverage report (under &#039;&#039;dataroot/codecoverage/$coveragedir&#039;&#039;) using:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$covrecorder-&amp;gt;generate_report();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Once more, that&#039;s all!&lt;br /&gt;
&lt;br /&gt;
==== Final notes ====&lt;br /&gt;
* Note that there are some more methods available in the moodle_coverage_recorder class. They will allow to control starting/stopping instrumentations by hand and other minor things but they shouldn&#039;t really be used. The run() and run_with_external_coverage() methods should be enough in 99% of cases.&lt;br /&gt;
* Not being part of the API, but used by it, there is one &#039;&#039;&#039;[http://cvs.moodle.org/moodle/admin/report/unittest/coveragefile.php?view=markup overagefile.php]&#039;&#039;&#039; script under &#039;&#039;admin/report/unittest&#039;&#039; responsible for serving the coverage report files from within Moodle. See current scripts in that dir to see how can be used.&lt;br /&gt;
* All the test execution / reporting / coverage utilities must be protected with the &#039;moodle/site:config&#039; permission.&lt;br /&gt;
&lt;br /&gt;
== A warning ==&lt;br /&gt;
&lt;br /&gt;
In &#039;xUnit Test Patterns&#039; there is a [http://xunitpatterns.com/TestAutomationRoadmap.html scale of testing difficulty] that goes from 1. to 6. Moodle is definitely at number 6. on that scale &#039;Non-object-oriented legacy software&#039;. It then goes recommend that you don&#039;t start to learn about unit testing with that sort of software :-(&lt;br /&gt;
&lt;br /&gt;
== Further reading about unit testing ==&lt;br /&gt;
&lt;br /&gt;
[http://manning.com/reiersol/ PHP in Action] has an excellent chapter explaining unit testing in PHP with &#039;&#039;simpletest&#039;&#039;. (Although the rest of that book advocates a style of programming that is very different from the style used in Moodle.)&lt;br /&gt;
&lt;br /&gt;
[http://www.pragprog.com/titles/utj/pragmatic-unit-testing-in-java-with-junit Pragmatic Unit Testing in Java with JUnit] is also a very good introduction, despite being in the wrong programming language. JUnit and Simpletest are very similar.&lt;br /&gt;
&lt;br /&gt;
[http://xunitpatterns.com/ xUnit Test Patterns] is the ultimate unit test book. I think it teaches you everything you could learn about unit testing by reading a book. The only way to learn more would be years of experience. It has really great advice for dealing with the kind of messy problems you get in a big, real project like Moodle. &lt;br /&gt;
&lt;br /&gt;
[[Category:Coding guidelines|Unit tests]]&lt;br /&gt;
[[Category:Quality Assurance]]&lt;/div&gt;</summary>
		<author><name>Azoltay</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/30/en/index.php?title=PHP_settings_by_Moodle_version&amp;diff=66160</id>
		<title>PHP settings by Moodle version</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/30/en/index.php?title=PHP_settings_by_Moodle_version&amp;diff=66160"/>
		<updated>2009-12-01T00:51:00Z</updated>

		<summary type="html">&lt;p&gt;Azoltay: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
and &lt;br /&gt;
{{Review}}{{Template:Installing Moodle}}&lt;br /&gt;
Moodle has different PHP requirements for different versions:&lt;br /&gt;
* Moodle 2.0 will require PHP 5.2.8 or later.&lt;br /&gt;
* Moodle 1.6 to 1.9 requires PHP 4.3.0 or later&lt;br /&gt;
* Moodle 1.0 to 1.5 requires PHP 4.1.0 or later &lt;br /&gt;
&lt;br /&gt;
==Other information==&lt;br /&gt;
** For Moodle version 1.4 or later: PHP4 (version 4.1.0 or later) or PHP5 (version 5.1.0 or later) are supported.&lt;br /&gt;
** For Moodle version 1.6 or later: the PHP4 (version 4.3.0 or later) or PHP5 (version 5.1.0 or later) are supported. &lt;br /&gt;
** Future Moodle versions 2.0 or later will require PHP5 (version 5.2.8 or later).&lt;br /&gt;
** PHP Settings. Check these settings in your php.ini or .htaccess file (if you&#039;re using Apache). For settings which use ON/OFF as their values, you can substitute 1 for ON and 0 for OFF if you prefer. &lt;br /&gt;
*** &#039;&#039;register_globals&#039;&#039; &#039;&#039;&#039;MUST&#039;&#039;&#039; be OFF&lt;br /&gt;
*** &#039;&#039;safe_mode&#039;&#039; needs to be OFF.&lt;br /&gt;
*** &#039;&#039;memory_limit&#039;&#039; should be at least 16M (32M is recommended for Moodle 1.7 and 40M for Moodle 1.8 or later). Large sites may need more than 128M. PHP 5.2.x requires higher memory_limit values than previous versions of PHP. 64bit operating systems require even more memory.&lt;br /&gt;
*** &#039;&#039;session.save_handler&#039;&#039; needs to be set to FILES.&lt;br /&gt;
*** &#039;&#039;magic_quotes_gpc&#039;&#039; should be ON. (It will be recommended to turn it off in 2.0.)&lt;br /&gt;
*** &#039;&#039;magic_quotes_runtime&#039;&#039; needs to be OFF.&lt;br /&gt;
*** &#039;&#039;file_uploads&#039;&#039; needs to be ON.&lt;br /&gt;
*** &#039;&#039;session.auto_start&#039;&#039; needs to be OFF.&lt;br /&gt;
*** &#039;&#039;session.bug_compat_warn&#039;&#039; needs to be OFF.&lt;br /&gt;
** PHP Extensions and libraries&lt;br /&gt;
*** The mbstring extension is recommended for Moodle 1.6 or later.&lt;br /&gt;
*** The iconv extension is recommended for Moodle 1.6 or later.&lt;br /&gt;
*** [http://www.libgd.org/ GD library] and the [http://www.freetype.org/ FreeType 2] library and extensions are needed to be able to look at the dynamic graphs that the logs pages make. (Freetype support is available as part of the GD extension for the 5.x versions of PHP)&lt;br /&gt;
*** The mysql extension is required if you are using the MySQL database. Note that in some Linux distributions (notably Red Hat) this is an optional installation.&lt;br /&gt;
*** The pgsql extension is required if you are using the PostgreSQL database.&lt;br /&gt;
*** The zlib extension is required for zip/unzip functionality.&lt;br /&gt;
*** The pdo and pdo_sqlite extensions are required for the (experimental) SQLite 3 database support.&lt;br /&gt;
*** The curl extension is recommended for Moodle 1.8 or later.&lt;br /&gt;
*** The tokenizer extension is recommended for Moodle 1.8 or later.&lt;br /&gt;
*** The curl and openssl extensions are required for the Moodle network functionality (Moodle 1.8 or later).&lt;br /&gt;
*** The xmlrpc extension is required for the Moodle network functionality (Moodle 1.8 or later).&lt;br /&gt;
*** The ctype extension is recommended for Moodle 1.8 or later. &lt;br /&gt;
*** Other PHP extensions may be required to support optional Moodle functionality, especially external authentication and/or enrolment (e.g. LDAP extension for LDAP authentication and the sockets extension for Chat server).&lt;br /&gt;
* A working database server: [[MySQL]] or [[PostgreSQL]] are completely supported and recommended for use with any version of Moodle. Support for Microsoft SQL Server and Oracle has been added in Moodle 1.7. MySQL is &#039;&#039;the&#039;&#039; choice for many people because it is very popular, but there are some [[Arguments in favour of PostgreSQL|arguments in favour of PostgreSQL]], especially if you are planning a large deployment.&lt;br /&gt;
** For Moodle 1.5, MySQL (version 3.23 or later) or PostgreSQL (7.4 or later). &lt;br /&gt;
** For Moodle 1.6, MySQL (version 4.1.12 or later) or PostgreSQL (7.4 or later).&lt;br /&gt;
** For Moodle 1.7, MySQL (version 4.1.12 or later), PostgreSQL (7.4 or later) or Microsoft SQL Server 2005 (version 9 or [http://moodle.org/mod/forum/discuss.php?d=59284 SQL Server Express 2005])&lt;br /&gt;
** For Moodle 1.8 or later, MySQL (version 4.1.12 or later), PostgreSQL (8.0 or later) or Microsoft SQL Server 2005 (version 9 or [http://moodle.org/mod/forum/discuss.php?d=59284 SQL Server Express 2005])&lt;br /&gt;
: MySQL Notes: For Moodle 1.6 or later, If you use latin languages only you can use MySQL 4.1.12. If you are using non-latin languages you require MySQL 4.1.16 or later. Currently the MySQL setting &amp;quot;strict mode&amp;quot; must be OFF (set to &amp;quot;&amp;quot; or &amp;quot;MYSQL40&amp;quot;) in the MySQL configuration file. &lt;br /&gt;
: PostgreSQL Notes: PostgreSQL 7.4 is recommended for earlier Moodle versions, since Moodle 1.8 only PostgreSQL 8.0 and above are supported.&lt;br /&gt;
* For showcases or low to medium-sized installations, Moodle 2.0 also includes (experimental) support for SQLite 3 database. This setup requires no database server, as the database file is stored in a local directory on the server.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
[[Installing Moodle]]&lt;br /&gt;
&lt;br /&gt;
[[de:PHP-Versionen für Moodle]]&lt;br /&gt;
[[ru:Настройки PHP для разных версий Moodle]]&lt;/div&gt;</summary>
		<author><name>Azoltay</name></author>
	</entry>
</feed>