<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/31/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hchathi</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/31/en/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hchathi"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/Special:Contributions/Hchathi"/>
	<updated>2026-04-18T14:00:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Password_salting&amp;diff=104998</id>
		<title>Password salting</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Password_salting&amp;diff=104998"/>
		<updated>2013-05-13T18:31:26Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* What is password salting? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Security}}&lt;br /&gt;
==What is password salting?==&lt;br /&gt;
&lt;br /&gt;
Passwords are stored in Moodle in a hashed form. Previously MD5 hashing was used, however in Moodle 2.5 onwards, new passwords are hashed using bcrypt.&lt;br /&gt;
&lt;br /&gt;
[http://en.wikipedia.org/wiki/Salt_%28cryptography%29 Password salting] is a way of making password hashing more secure by adding a random string of characters to passwords before their hash is calculated, which makes them harder to reverse (the longer the random string, the harder you make it).&lt;br /&gt;
&lt;br /&gt;
==Enabling password salting==&lt;br /&gt;
&lt;br /&gt;
To set a password salt, add the following line to your [[Configuration file|config.php file]]:&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltmain = &#039;some long random string here with lots of characters&#039;;&lt;br /&gt;
&lt;br /&gt;
The random string of characters should be a mix of letters, numbers and other characters. The [http://dev.moodle.org/gensalt.php Moodle Salt Generator] may be used to obtain a suitable long random string. A string length of at least 40 characters is recommended.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note&#039;&#039;: For security reasons the only way to enable password salting is by editing config.php - there is no way to do so in the Moodle interface.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tip&#039;&#039;: Keep a note of your password salt somewhere other than config.php to prevent the situation of your password salt being lost and all site users having to go through password recovery to reset their passwords.&lt;br /&gt;
&lt;br /&gt;
==Changing the salt==&lt;br /&gt;
&lt;br /&gt;
If for any reason you wish to change the salt, the old salt must be retained in config.php in addition to the new salt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;passwordsaltmain&amp;lt;/code&amp;gt; should be changed to &amp;lt;code&amp;gt;passwordsaltalt1&amp;lt;/code&amp;gt; (note that the exact expressions must be used) for the old salt as follows:&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltalt1 = &#039;old long random string&#039;;&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltmain = &#039;new long random string&#039;;&lt;br /&gt;
&lt;br /&gt;
If you change your salt again in the future, you must retain all the previous salts for some time (until every user has logged in at least once, so they start using the new salt). You can use $CFG-&amp;gt;passwordsaltalt2, $CFG-&amp;gt;passwordsaltalt3, etc. to keep up to 20 previous salts.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Warning: If you change the salt and do not retain the old one in config.php you will no longer be able to login to your site!&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Disabling password salting==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Not Recommended! Once enabled, you should leave password salt enabled.&lt;br /&gt;
&lt;br /&gt;
To disable password salting in Moodle, you can delete, comment out, or change the value of passwordsaltmain to &amp;quot;empty&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 // EXAMPLE: set to empty string&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltmain = &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // EXAMPLE: comment out&lt;br /&gt;
 /*&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltmain = &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;;&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
However, you are not done! You &#039;&#039;&#039;must also move the old salt to an &amp;quot;alt&amp;quot; value&#039;&#039;&#039;, just like the &amp;quot;changing the salt&amp;quot; description, above:&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltalt1 = &#039;old long random string&#039;;&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltmain = &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
==Importing users from another site==&lt;br /&gt;
&lt;br /&gt;
If you import users from another Moodle site which uses a password salt, you need to add the other site&#039;s salt to config.php too. Upto 20 alternate salts may be added&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;passwordsaltalt1, $CFG-&amp;gt;passwordsaltalt2, ...  $CFG-&amp;gt;passwordsaltalt20&lt;br /&gt;
&lt;br /&gt;
==How does password salting work?==&lt;br /&gt;
&lt;br /&gt;
When a password is checked, the code looks for &amp;lt;code&amp;gt;CFG-&amp;gt;passwordsaltmain&amp;lt;/code&amp;gt;. If set, salt is appended to user&#039;s password before calculating the hash.&lt;br /&gt;
&lt;br /&gt;
If the unsalted hash of a user&#039;s password validates, it is assumed that the salt was set for the first time since the last time the user logged in. The user&#039;s password is upgraded, using the salt. &#039;&#039;&#039;The password is salted during the first login after the salt was set in config.php.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If neither the unsalted hash, or the salted hash validates, the code looks for up to 20 alternate salts.&lt;br /&gt;
&lt;br /&gt;
If you change salts, in order not to orphan existing user accounts, you must enter the old salt into one of the alternate slots.&lt;br /&gt;
&lt;br /&gt;
When a user who has an &amp;quot;old salt&amp;quot; password logs in, the first test of their authentication with the new salt will fail... then the code will test any alternate salts, looking for one that allows the password to be proven valid.&lt;br /&gt;
&lt;br /&gt;
If a user is deemed valid, the system will upgrade the user&#039;s hashed password to the latest salt.&lt;br /&gt;
&lt;br /&gt;
[[cs:Solení hesel]]&lt;br /&gt;
[[de:Kennwortverschlüsselung (Salt)]]&lt;br /&gt;
[[es:report/security/report_security_check_passwordsaltmain]]&lt;br /&gt;
[[fr:Salage de mot de passe]]&lt;br /&gt;
[[it:report/security/report_security_check_passwordsaltmain]]&lt;br /&gt;
[[nl:report/security/report_security_check_passwordsaltmain]]&lt;br /&gt;
[[ja:パスワードSALT]]&lt;br /&gt;
[[ru:Зашумление паролей]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:Modules_and_plugins_replacement_proposal&amp;diff=82175</id>
		<title>Development talk:Modules and plugins replacement proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:Modules_and_plugins_replacement_proposal&amp;diff=82175"/>
		<updated>2011-03-22T14:50:16Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Comments */ new section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Some minor suggestions from Tim (so much for the request not to comment yet):&lt;br /&gt;
&lt;br /&gt;
* This may be a version 2.0 feature, but simple links from the database entries to the place on AMOS where people need to go to translate this plugin, and back again.&lt;br /&gt;
* In terms of which version of core Moodle the plugins works with, there are big advantages if this information can remain in version.php, where it is readable by the Moodle install code. The MnP database could automatically read the data out of there to display on the web, like AMOS gets strings out of version control.&lt;br /&gt;
&lt;br /&gt;
In the database schema:&lt;br /&gt;
* Rather than separate local_contrib_plugin_contributor.creator/active columns, would it be better to have a single contributortype column? Easier to extend in future.&lt;br /&gt;
* Should userid be in local_contrib_review or local_contrib_review_outcome?&lt;br /&gt;
* If there a good reason for using &#039;softwareversion&#039; in names? moodleversion would make it clearer. Of course, that is less generic.&lt;br /&gt;
* should local_contrib_review_outcomes have a machine-readable column that holds a status like pass/fail, as well as the text in review?&lt;br /&gt;
* Do you really need hierarchical categories. They are a pain in SQL, and they add UI complexity. I think one-level categories may be fine, particularly if you have tags as well.&lt;br /&gt;
&lt;br /&gt;
In terms of display, it would be nice if you could use group icons from using Moodle (like core-developer, Partner, PHM) when displaying users. It would be useful if people could see that a review was by a core developer.&lt;br /&gt;
&lt;br /&gt;
I had not realised that the file API did not support local plugins. See https://github.com/moodle/moodle/blob/master/pluginfile.php#L738&lt;br /&gt;
&lt;br /&gt;
Would a capability like &amp;quot;new entries from this user approved automatically&amp;quot; and &amp;quot;new versions from this user approved automatically&amp;quot; be worthwhile? I believe the current system overloads the approve capability for this, which causes pain.&lt;br /&gt;
&lt;br /&gt;
--[[User:Tim Hunt|Tim Hunt]] 09:17, 12 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Hi Tim,&lt;br /&gt;
Thanks for the early feedback, all good suggestions/observations.&lt;br /&gt;
In response to the points you have raised:&lt;br /&gt;
* AMOS links make VERY good sense and I&#039;m sure I&#039;ll be able to easily fit them in.&lt;br /&gt;
* Good suggestion, I still have to talk to Martin about how things will be stored, however where practical if possible it would be great if we could utilise version.php&lt;br /&gt;
* Interesting idea, I had separated the two as the creator may no longer be active (passed the responsibility onto others). Perhaps if active is made contributortype that would allow us to extend in the future (primary or owner being an obvious extension).&lt;br /&gt;
* userid I think should be local_contrib_review, there will be a record created there for each individual review which will consist of the general review stored within that record, and then several criteria reviews stored in local_contrib_review_outcome. Does that make sense? Remembering of course this is all very fresh and it may be me misunderstanding something here.&lt;br /&gt;
* Yes, softwareversion isn&#039;t the greatest I did refrain from calling it moodleversion to keep the project more easily diversable, however I have yet to talk to Martin about that prospect... not too sure what he will want but I&#039;ll leave that one up to him.&lt;br /&gt;
* In regards to local_contrib_review_outcome I was intending to you the core rating system for that, however it would require core changes presently. If the rating system isn&#039;t used then it will certainly need that column. Also I will have to at some point consider performance, I haven&#039;t looked at the ratings internal but if it isn&#039;t joinable in a friendly way then it may be worth duplicating that information in the local_contrib_review_outcome table for quicker lookups.&lt;br /&gt;
* Group icons === awesome idea which I will be sure to work in.&lt;br /&gt;
* Haha quite right it does support files, I&#039;ve updated the doc now. I had given it a quick glance and misread the above else thinking anything with an underscore entered there..... just another reason I should read more carefully. Thanks for pointing that out.&lt;br /&gt;
* Yes to both the capability suggestions, there had been talk about automating that some how and capabilities for it would be perfect.&lt;br /&gt;
&lt;br /&gt;
Again thank you, I&#039;ll amend the rest of the doc shortly.&lt;br /&gt;
&lt;br /&gt;
Cheers&lt;br /&gt;
&lt;br /&gt;
--[[User:Sam Hemelryk|Sam Hemelryk]] 09:48, 12 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Initial comments from David ==&lt;br /&gt;
&lt;br /&gt;
* overall - sounds good! :-)&lt;br /&gt;
* re links to AMOS - easy to implement now as AMOS already supports permalinks to its filter so it is easy to construct URL that leads the user directly to a page where a given component on a given branch is translated&lt;br /&gt;
* what I miss in the document is a mention of some webservices support. We will either need webservice layer or maybe better just a script that generates plugins info into a big XML file. Such file will describe all the plugins and the location of their sources. This file will be then fetch regularly by Moodle sites&#039; plugin_manager that will allow remote update/installation via the web. I am willing to work on this part once we branch MOODLE_20_STABLE, though there is no spec yet, sorry. The goal is to allow simple installations of extensions from the Moodle admin interface - similarly to what Wordpress does&lt;br /&gt;
* that XML file would be used by AMOS, too, so that it knows what plugins and their branches it should track&lt;br /&gt;
&lt;br /&gt;
--[[User:David Mudrak|David Mudrak]] 10:57, 12 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Hi David&lt;br /&gt;
&lt;br /&gt;
Thanks for looking it over and having a think about it. I&#039;ve been working on the proposal again today and building it up more and more.&lt;br /&gt;
&lt;br /&gt;
In reply to your points:&lt;br /&gt;
&lt;br /&gt;
* Awesome that AMOS has a predictable link structure, it certainly will be cool to integrate the two system.&lt;br /&gt;
* There is now information about RSS feeds and web services that the new system will be able to process. The idea of having everything available from the admin interface of your Moodle installation is great. I&#039;m not too sure presently what Martins plans for undertaking such work are, however he did ask for it to be provisioned where/if possible within this new system.&lt;br /&gt;
* I would like to talk to you at some point after Martin is back to find out how we could best integrate this system with AMOS. It&#039;d be great to see where we could take it and I&#039;m sure you&#039;d have the best idea about what is possible there. I&#039;ll get in touch with you after I&#039;ve talked to Martin and organise a time to discuss it.&lt;br /&gt;
&lt;br /&gt;
Cheers&lt;br /&gt;
&lt;br /&gt;
--[[User:Sam Hemelryk|Sam Hemelryk]] 08:40, 13 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Why did you just strip local_ from the front of all the table names. I thought that all DB tables were meant to start with the frankenstyle plugin name?--[[User:Tim Hunt|Tim Hunt]] 10:26, 19 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Hi Tim, I removed &#039;&#039;local_&#039;&#039; after finding the 28 character table name limit imposed by XMLDB. I choose to remove &#039;&#039;local_&#039;&#039; rather than using cryptic names. --[[User:Sam Hemelryk|Sam Hemelryk]] 06:56, 21 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: I know the 28 character table name limit is a pain, but we all have to live with it. I still don&#039;t see why you should be able to break the coding guidelines. I was specifying something yesterday, and eventually I was able to find table names that fitted and were sensible.&lt;br /&gt;
&lt;br /&gt;
:: Also, while you claim your table names are non-crypic becuase they are long, actually, while trying to think of better names, I completely misunderstood what the collection thing was about. I thought it was for dealing with the situation where you have, for example, a block and an admin report that, while being separate plugins, rely on each other, so you want to offer them for download as a single package. However, when I read the detail of the document, I find that is wrong. So, collection is not only a long word, it is also ambiguous.&lt;br /&gt;
&lt;br /&gt;
:: Anyway, here are my suggestion to get you within the limit:&lt;br /&gt;
&lt;br /&gt;
:: review_criterion -&amp;gt; review_test. collection -&amp;gt; set (does not really solve the ambiguous naming, but at least is short. I think a significant part of your problem is that this concept overlaps very heavily with tags, but presumably you want tags to be crowd-sourced). Then I would cop out and just use an abbreviation for version, say ver or vers. That solves the rest of your problems. &lt;br /&gt;
&lt;br /&gt;
   1234567890123456789012345678&lt;br /&gt;
   local_contrib_plugin&lt;br /&gt;
   local_contrib_vers&lt;br /&gt;
   local_contrib_vers_download&lt;br /&gt;
   local_contrib_category&lt;br /&gt;
   local_contrib_contributor&lt;br /&gt;
   local_contrib_set&lt;br /&gt;
   local_contrib_set_plugin&lt;br /&gt;
   local_contrib_software_vers&lt;br /&gt;
   local_contrib_supported_vers&lt;br /&gt;
   local_contrib_review&lt;br /&gt;
   local_contrib_review_test&lt;br /&gt;
   local_contrib_review_outcome&lt;br /&gt;
   local_contrib_awards&lt;br /&gt;
   local_contrib_plugin_awards&lt;br /&gt;
   1234567890123456789012345678&lt;br /&gt;
&lt;br /&gt;
::I think the best solution to the ambiguity of what some of the table names means is better table comments. At the moment, some of the comments only make sense if you have read the full spec, which will not be try for people who are just looking at the code.--[[User:Tim Hunt|Tim Hunt]] 08:43, 21 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Hi Tim, thanks for the feedback.&lt;br /&gt;
&lt;br /&gt;
The 28 character table name limit is a bit of a pain, but I do see your point and happy to add &#039;&#039;local_&#039;&#039; back into the mix and refactor the table names as suggested.&lt;br /&gt;
&lt;br /&gt;
Your observations regarding collections are correct, it is very similar to tags however only those with the required capabilities will be able to manage/add to them. The name collections is perhaps a bit vague and as it will be way to long I think using &#039;&#039;set&#039;&#039; instead is a good idea.&lt;br /&gt;
&lt;br /&gt;
I will also go through and revise the table comments :)&lt;br /&gt;
&lt;br /&gt;
Cheers --[[User:Sam Hemelryk|Sam Hemelryk]] 01:41, 24 January 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== typo? ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&#039;Version control systems and downloads&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this new system we will start collecting information about the version control system that the contributor is using. We gather this information for each version of a plugin that is created and are able to collect some or all of the following: &#039;&#039;&#039;&#039;the new of the vcs system&#039;&#039;&#039;&#039;...&lt;br /&gt;
&lt;br /&gt;
the new &#039;&#039;what&#039;&#039; of &#039;&#039;what&#039;&#039; system?&lt;br /&gt;
--[[User:Joseph Rézeau|Joseph Rézeau]] 17:14, 2 February 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Thanks Joseph, I&#039;ve corrected that now.&lt;br /&gt;
It should have read &#039;&#039;some or all of the following: the vcs system (git, cvs, svn, other), ...&#039;&#039;&lt;br /&gt;
&amp;lt;br /&amp;gt;Cheers&lt;br /&gt;
&amp;lt;br /&amp;gt;--[[User:Sam Hemelryk|Sam Hemelryk]] 03:53, 4 February 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Contrib packages (aka, bundling multiple plugins together) ==&lt;br /&gt;
&lt;br /&gt;
This is just a reminder about the current contrib-packages that we are building since ages ago. Is going to be some way to group different plugins and build one package automatically? I think it can help in a lot of situations. Not critical, but interesting IMO. You can ask Anthony about how that is being handled now and how it could be integrated in the new M&amp;amp;P stuff.&lt;br /&gt;
&lt;br /&gt;
[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:29, 2 February 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: Thanks for the reminder Eloy, I had originally talked to Martin about this in the very early discussions about this system but will raise it with him again. It wouldn&#039;t be too hard to do something there I&#039;m sure (depending on how far down the rabbit hole we choose to go).&lt;br /&gt;
:: --[[User:Sam Hemelryk|Sam Hemelryk]] 03:55, 4 February 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Proposal to change status field in local_contrib_vers ==&lt;br /&gt;
&lt;br /&gt;
Please note that Moodle 2.0 now defines MATURITY_xxx constants in setuplib.php that are used to mark a maturity level of core or a plugin (alpha, beta, rc, stable). I suggest to use these constants instead of a string for the fields &#039;status&#039; in local_contrib_vers. In the future, plugins are expected to define things like&lt;br /&gt;
&lt;br /&gt;
    $module-&amp;gt;maturity = MATURITY_STABLE;&lt;br /&gt;
&lt;br /&gt;
in their version.php and this value will be used at the plugins report, too. NULL value means &#039;unknown&#039;. You may also consider changing the name of the field to &#039;maturity&#039;.&lt;br /&gt;
&lt;br /&gt;
Alternatively, we could use both. New &#039;maturity&#039; field for the integer constant value and &#039;status&#039; for additional comment. --[[User:David Mudrak|David Mudrak]] 09:47, 8 March 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Comments ==&lt;br /&gt;
&lt;br /&gt;
It would be nice if users who aren&#039;t logged in could see plugin comments (MDLSITE-1255) --[[User:Hubert Chathi|Hubert Chathi]] 14:50, 22 March 2011 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=User:Hubert_Chathi&amp;diff=81809</id>
		<title>User:Hubert Chathi</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=User:Hubert_Chathi&amp;diff=81809"/>
		<updated>2011-03-08T16:40:34Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: See my [http://moodle.org/user/profile.php?id=706541 Moodle profile page] for more information.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See my [http://moodle.org/user/profile.php?id=706541 Moodle profile page] for more information.&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81808</id>
		<title>Development talk:Scheduled Tasks Proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81808"/>
		<updated>2011-03-08T16:38:47Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pseudo code proposal ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This is just a rough idea to provoke thought:--[[User:Tim Hunt|Tim Hunt]] 11:06, 9 December 2009 (UTC)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
function handle_cron($maxprocesstime) {&lt;br /&gt;
    $timestart = time();&lt;br /&gt;
&lt;br /&gt;
    $runid = cron_record_starting_processing($timenow);&lt;br /&gt;
&lt;br /&gt;
    while (($timenow = time()) &amp;lt; $timestart + $maxprocesstime) {&lt;br /&gt;
        try {&lt;br /&gt;
            $task = cron_get_next_task($timenow);&lt;br /&gt;
            cron_acquire_lock($task);&lt;br /&gt;
            $next = $task-&amp;gt;execute($timenow);&lt;br /&gt;
            cron_record_task_success($task, $next, $timenow);&lt;br /&gt;
            cron_release_lock($task);&lt;br /&gt;
&lt;br /&gt;
        } catch (Exception $e) {&lt;br /&gt;
            cron_record_task_failure($task, $timenow, $e);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cron_record_ending_processing($runid, $timenow);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Instances of this class are rows in the scheduled_tasks table.&lt;br /&gt;
 */&lt;br /&gt;
abstract class scheduled_task {&lt;br /&gt;
    protected $id;&lt;br /&gt;
    protected $plugin; // = &#039;mod_quiz&#039;, &#039;qtype_multichoice&#039;.&lt;br /&gt;
    protected $function;&lt;br /&gt;
    protected $lastruntime;&lt;br /&gt;
    protected $nextscheduledtime;&lt;br /&gt;
    protected $priority; // LOW, MEDIUM, HIGH, or, a number like nice 19, or something.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow);&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow);&lt;br /&gt;
&lt;br /&gt;
    public function execute($timenow) {&lt;br /&gt;
        $file = get_plugin_dir($this-&amp;gt;plugin) . &#039;/cron.php&#039;;&lt;br /&gt;
        if (!is_readable($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file does not exist.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        if (include_once($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file could not be included.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        list($start, $end) = next_times($timenow);&lt;br /&gt;
        $this-&amp;gt;$function($start, $end);&lt;br /&gt;
        return $this-&amp;gt;schedule_next();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class one_off_task extends scheduled_task {&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array(null, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class catchup_task extends scheduled_task {&lt;br /&gt;
    protected $desiredinterval; // seconds&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array($lastruntime, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return $timenow + $desiredinterval;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class every_day_task extends scheduled_task {&lt;br /&gt;
    protected $swtichovertime; // Seconds after midnight.&lt;br /&gt;
    protected $runtime; // Seconds after midnight.&lt;br /&gt;
    // For now this code assumes $runtime &amp;gt; $swtichovertime, but that is just me&lt;br /&gt;
    // being lazy. It can be fixed.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $previousmidnight = get_previous_midnight($midnight);&lt;br /&gt;
        $starttime = $previousmidnight + $swtichovertime;&lt;br /&gt;
        $endtime = $midnight + $swtichovertime;&lt;br /&gt;
        return array($starttime, $endtime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $nextmidnight = get_following_midnight($midnight);&lt;br /&gt;
        return $nextmidnight + $this-&amp;gt;runtime;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class weekly_task  extends scheduled_task {&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Approximate database tables.&lt;br /&gt;
&lt;br /&gt;
scheduled_tasks&lt;br /&gt;
    id AUTOINCREMENT&lt;br /&gt;
    type varchar&lt;br /&gt;
    plugin varchar&lt;br /&gt;
    function varchar UNIQUE&lt;br /&gt;
    lastruntime int &lt;br /&gt;
    nextscheduledtime int&lt;br /&gt;
    priority int&lt;br /&gt;
    custom1 int&lt;br /&gt;
    custom2 int &lt;br /&gt;
    customextra text&lt;br /&gt;
&lt;br /&gt;
scheduled_task_locks&lt;br /&gt;
    id int auto&lt;br /&gt;
    function fk unique&lt;br /&gt;
    locktime int&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Proposed database changes ==&lt;br /&gt;
&lt;br /&gt;
We will be implementing a scheduled tasks system in our product, but we need a couple of extra features.  In the interest of interoperability and not reinventing cron too many times, here are the features that we need, and the database changes that would be required:&lt;br /&gt;
* plugins need to define multiple cron jobs on-the-fly (one of our plugins will allow the user to schedule several tasks with different schedules), and allow plugins to modify those tasks&lt;br /&gt;
* ability to specify that a task should run n times, or until [date]&lt;br /&gt;
&lt;br /&gt;
For the first requirement, I&#039;d like to add a taskcode field to the DB, to allow plugins to identify the different tasks that it creates.  The callfunction would then be called with taskcode as an argument.&lt;br /&gt;
&lt;br /&gt;
For the second requirement, I think that we can roll the onceoff_tasks table into the main tasks table, and just add extra fields for number of times remaining and/or end date.  So onceoff tasks would just be a task with the number of runs remaining set to 1, nextruntime set to the time that it should run, and the cron fields set to (empty? or &amp;quot;*&amp;quot;?).  With the taskcode field, we wouldn&#039;t need the customdata field -- the task can use the taskcode field to identify the task, and load customdata from its own table.&lt;br /&gt;
&lt;br /&gt;
Here is my proposed table, with changes highlighted:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;scheduled_tasks:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|plugintype&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|plugintype - should match the path-style declarations in get_plugin_types (eg question/type, not qtype).  Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|pluginname&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|name of the plugin. Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;taskcode&#039;&#039;&#039; (new)&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|a plugin-specific identifier for the task, used to differentiate between multiple tasks for the same plugin&lt;br /&gt;
|-&lt;br /&gt;
|callfunction&lt;br /&gt;
|varchar(200) &amp;lt;strike&amp;gt;(unique)&amp;lt;/strike&amp;gt;&lt;br /&gt;
|the function to call. &amp;lt;strike&amp;gt;Must be unique, as it will be used for the locking.&amp;lt;/strike&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lastruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|nextruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|blocking&lt;br /&gt;
|int(1)&lt;br /&gt;
|0 or 1 - whether this task, when running, blocks everything else from running.&lt;br /&gt;
|-&lt;br /&gt;
|minute&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|hour&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|day&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|month&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|dayofweek&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;runsremaining&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Number of times that the task will run&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;enddate&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Task will not run after this date&lt;br /&gt;
|-&lt;br /&gt;
|customised&lt;br /&gt;
|integer(1)&lt;br /&gt;
|0 or 1 - whether this time differs from what is in code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Since we can now have multiple tasks with the same callfunction, we can&#039;t enforce that it be unique.  So we can either use (taskcode,callfunction) or (plugintype,pluginname,taskcode) as the key for locking.&lt;br /&gt;
&lt;br /&gt;
Also, do we need a field to specify which file the callfunction is in?&lt;br /&gt;
&lt;br /&gt;
--[[User:Hubert Chathi|Hubert Chathi]] 14:45, 8 March 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Looks reasonable. I wonder if taskname would be better than taskcode?--[[User:Tim Hunt|Tim Hunt]] 16:28, 8 March 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Yeah, I started with taskname, then thought taskcode might be better.  I don&#039;t mind either way. --[[User:Hubert Chathi|Hubert Chathi]] 16:38, 8 March 2011 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81807</id>
		<title>Development talk:Scheduled Tasks Proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81807"/>
		<updated>2011-03-08T16:38:14Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pseudo code proposal ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This is just a rough idea to provoke thought:--[[User:Tim Hunt|Tim Hunt]] 11:06, 9 December 2009 (UTC)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
function handle_cron($maxprocesstime) {&lt;br /&gt;
    $timestart = time();&lt;br /&gt;
&lt;br /&gt;
    $runid = cron_record_starting_processing($timenow);&lt;br /&gt;
&lt;br /&gt;
    while (($timenow = time()) &amp;lt; $timestart + $maxprocesstime) {&lt;br /&gt;
        try {&lt;br /&gt;
            $task = cron_get_next_task($timenow);&lt;br /&gt;
            cron_acquire_lock($task);&lt;br /&gt;
            $next = $task-&amp;gt;execute($timenow);&lt;br /&gt;
            cron_record_task_success($task, $next, $timenow);&lt;br /&gt;
            cron_release_lock($task);&lt;br /&gt;
&lt;br /&gt;
        } catch (Exception $e) {&lt;br /&gt;
            cron_record_task_failure($task, $timenow, $e);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cron_record_ending_processing($runid, $timenow);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Instances of this class are rows in the scheduled_tasks table.&lt;br /&gt;
 */&lt;br /&gt;
abstract class scheduled_task {&lt;br /&gt;
    protected $id;&lt;br /&gt;
    protected $plugin; // = &#039;mod_quiz&#039;, &#039;qtype_multichoice&#039;.&lt;br /&gt;
    protected $function;&lt;br /&gt;
    protected $lastruntime;&lt;br /&gt;
    protected $nextscheduledtime;&lt;br /&gt;
    protected $priority; // LOW, MEDIUM, HIGH, or, a number like nice 19, or something.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow);&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow);&lt;br /&gt;
&lt;br /&gt;
    public function execute($timenow) {&lt;br /&gt;
        $file = get_plugin_dir($this-&amp;gt;plugin) . &#039;/cron.php&#039;;&lt;br /&gt;
        if (!is_readable($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file does not exist.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        if (include_once($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file could not be included.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        list($start, $end) = next_times($timenow);&lt;br /&gt;
        $this-&amp;gt;$function($start, $end);&lt;br /&gt;
        return $this-&amp;gt;schedule_next();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class one_off_task extends scheduled_task {&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array(null, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class catchup_task extends scheduled_task {&lt;br /&gt;
    protected $desiredinterval; // seconds&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array($lastruntime, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return $timenow + $desiredinterval;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class every_day_task extends scheduled_task {&lt;br /&gt;
    protected $swtichovertime; // Seconds after midnight.&lt;br /&gt;
    protected $runtime; // Seconds after midnight.&lt;br /&gt;
    // For now this code assumes $runtime &amp;gt; $swtichovertime, but that is just me&lt;br /&gt;
    // being lazy. It can be fixed.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $previousmidnight = get_previous_midnight($midnight);&lt;br /&gt;
        $starttime = $previousmidnight + $swtichovertime;&lt;br /&gt;
        $endtime = $midnight + $swtichovertime;&lt;br /&gt;
        return array($starttime, $endtime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $nextmidnight = get_following_midnight($midnight);&lt;br /&gt;
        return $nextmidnight + $this-&amp;gt;runtime;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class weekly_task  extends scheduled_task {&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Approximate database tables.&lt;br /&gt;
&lt;br /&gt;
scheduled_tasks&lt;br /&gt;
    id AUTOINCREMENT&lt;br /&gt;
    type varchar&lt;br /&gt;
    plugin varchar&lt;br /&gt;
    function varchar UNIQUE&lt;br /&gt;
    lastruntime int &lt;br /&gt;
    nextscheduledtime int&lt;br /&gt;
    priority int&lt;br /&gt;
    custom1 int&lt;br /&gt;
    custom2 int &lt;br /&gt;
    customextra text&lt;br /&gt;
&lt;br /&gt;
scheduled_task_locks&lt;br /&gt;
    id int auto&lt;br /&gt;
    function fk unique&lt;br /&gt;
    locktime int&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Proposed database changes ==&lt;br /&gt;
&lt;br /&gt;
We will be implementing a scheduled tasks system in our product, but we need a couple of extra features.  In the interest of interoperability and not reinventing cron too many times, here are the features that we need, and the database changes that would be required:&lt;br /&gt;
* plugins need to define multiple cron jobs on-the-fly (one of our plugins will allow the user to schedule several tasks with different schedules), and allow plugins to modify those tasks&lt;br /&gt;
* ability to specify that a task should run n times, or until [date]&lt;br /&gt;
&lt;br /&gt;
For the first requirement, I&#039;d like to add a taskcode field to the DB, to allow plugins to identify the different tasks that it creates.  The callfunction would then be called with taskcode as an argument.&lt;br /&gt;
&lt;br /&gt;
For the second requirement, I think that we can roll the onceoff_tasks table into the main tasks table, and just add extra fields for number of times remaining and/or end date.  So onceoff tasks would just be a task with the number of runs remaining set to 1, nextruntime set to the time that it should run, and the cron fields set to (empty? or &amp;quot;*&amp;quot;?).  With the taskcode field, we wouldn&#039;t need the customdata field -- the task can use the taskcode field to identify the task, and load customdata from its own table.&lt;br /&gt;
&lt;br /&gt;
Here is my proposed table, with changes highlighted:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;scheduled_tasks:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|plugintype&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|plugintype - should match the path-style declarations in get_plugin_types (eg question/type, not qtype).  Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|pluginname&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|name of the plugin. Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;taskcode&#039;&#039;&#039; (new)&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|a plugin-specific identifier for the task, used to differentiate between multiple tasks for the same plugin&lt;br /&gt;
|-&lt;br /&gt;
|callfunction&lt;br /&gt;
|varchar(200) &amp;lt;strike&amp;gt;(unique)&amp;lt;/strike&amp;gt;&lt;br /&gt;
|the function to call. &amp;lt;strike&amp;gt;Must be unique, as it will be used for the locking.&amp;lt;/strike&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lastruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|nextruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|blocking&lt;br /&gt;
|int(1)&lt;br /&gt;
|0 or 1 - whether this task, when running, blocks everything else from running.&lt;br /&gt;
|-&lt;br /&gt;
|minute&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|hour&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|day&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|month&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|dayofweek&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;runsremaining&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Number of times that the task will run&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;enddate&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Task will not run after this date&lt;br /&gt;
|-&lt;br /&gt;
|customised&lt;br /&gt;
|integer(1)&lt;br /&gt;
|0 or 1 - whether this time differs from what is in code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Since we can now have multiple tasks with the same callfunction, we can&#039;t enforce that it be unique.  So we can either use (taskcode,callfunction) or (plugintype,pluginname,taskcode) as the key for locking.&lt;br /&gt;
&lt;br /&gt;
Also, do we need a field to specify which file the callfunction is in?&lt;br /&gt;
&lt;br /&gt;
--[[User:Hubert Chathi|Hubert Chathi]] 14:45, 8 March 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Looks reasonable. I wonder if taskname would be better than taskcode?--[[User:Tim Hunt|Tim Hunt]] 16:28, 8 March 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
Yeah, I started with taskname, then thought taskcode might be better.  I don&#039;t mind either way.&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81800</id>
		<title>Development talk:Scheduled Tasks Proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:Scheduled_Tasks_Proposal&amp;diff=81800"/>
		<updated>2011-03-08T14:45:34Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Pseudo code proposal ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This is just a rough idea to provoke thought:--[[User:Tim Hunt|Tim Hunt]] 11:06, 9 December 2009 (UTC)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
function handle_cron($maxprocesstime) {&lt;br /&gt;
    $timestart = time();&lt;br /&gt;
&lt;br /&gt;
    $runid = cron_record_starting_processing($timenow);&lt;br /&gt;
&lt;br /&gt;
    while (($timenow = time()) &amp;lt; $timestart + $maxprocesstime) {&lt;br /&gt;
        try {&lt;br /&gt;
            $task = cron_get_next_task($timenow);&lt;br /&gt;
            cron_acquire_lock($task);&lt;br /&gt;
            $next = $task-&amp;gt;execute($timenow);&lt;br /&gt;
            cron_record_task_success($task, $next, $timenow);&lt;br /&gt;
            cron_release_lock($task);&lt;br /&gt;
&lt;br /&gt;
        } catch (Exception $e) {&lt;br /&gt;
            cron_record_task_failure($task, $timenow, $e);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    cron_record_ending_processing($runid, $timenow);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Instances of this class are rows in the scheduled_tasks table.&lt;br /&gt;
 */&lt;br /&gt;
abstract class scheduled_task {&lt;br /&gt;
    protected $id;&lt;br /&gt;
    protected $plugin; // = &#039;mod_quiz&#039;, &#039;qtype_multichoice&#039;.&lt;br /&gt;
    protected $function;&lt;br /&gt;
    protected $lastruntime;&lt;br /&gt;
    protected $nextscheduledtime;&lt;br /&gt;
    protected $priority; // LOW, MEDIUM, HIGH, or, a number like nice 19, or something.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow);&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow);&lt;br /&gt;
&lt;br /&gt;
    public function execute($timenow) {&lt;br /&gt;
        $file = get_plugin_dir($this-&amp;gt;plugin) . &#039;/cron.php&#039;;&lt;br /&gt;
        if (!is_readable($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file does not exist.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        if (include_once($file)) {&lt;br /&gt;
            throw new cron_exception(&#039;required file could not be included.&#039;);&lt;br /&gt;
        }&lt;br /&gt;
        list($start, $end) = next_times($timenow);&lt;br /&gt;
        $this-&amp;gt;$function($start, $end);&lt;br /&gt;
        return $this-&amp;gt;schedule_next();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class one_off_task extends scheduled_task {&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array(null, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class catchup_task extends scheduled_task {&lt;br /&gt;
    protected $desiredinterval; // seconds&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        return array($lastruntime, $timenow);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        return $timenow + $desiredinterval;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class every_day_task extends scheduled_task {&lt;br /&gt;
    protected $swtichovertime; // Seconds after midnight.&lt;br /&gt;
    protected $runtime; // Seconds after midnight.&lt;br /&gt;
    // For now this code assumes $runtime &amp;gt; $swtichovertime, but that is just me&lt;br /&gt;
    // being lazy. It can be fixed.&lt;br /&gt;
&lt;br /&gt;
    protected abstract function get_start_end_times($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $previousmidnight = get_previous_midnight($midnight);&lt;br /&gt;
        $starttime = $previousmidnight + $swtichovertime;&lt;br /&gt;
        $endtime = $midnight + $swtichovertime;&lt;br /&gt;
        return array($starttime, $endtime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    protected abstract function schedule_next($timenow) {&lt;br /&gt;
        $midnight = get_midnight_before($this-&amp;gt;nextscheduledtime);&lt;br /&gt;
        $nextmidnight = get_following_midnight($midnight);&lt;br /&gt;
        return $nextmidnight + $this-&amp;gt;runtime;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class weekly_task  extends scheduled_task {&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Approximate database tables.&lt;br /&gt;
&lt;br /&gt;
scheduled_tasks&lt;br /&gt;
    id AUTOINCREMENT&lt;br /&gt;
    type varchar&lt;br /&gt;
    plugin varchar&lt;br /&gt;
    function varchar UNIQUE&lt;br /&gt;
    lastruntime int &lt;br /&gt;
    nextscheduledtime int&lt;br /&gt;
    priority int&lt;br /&gt;
    custom1 int&lt;br /&gt;
    custom2 int &lt;br /&gt;
    customextra text&lt;br /&gt;
&lt;br /&gt;
scheduled_task_locks&lt;br /&gt;
    id int auto&lt;br /&gt;
    function fk unique&lt;br /&gt;
    locktime int&lt;br /&gt;
*/&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Proposed database changes ==&lt;br /&gt;
&lt;br /&gt;
We will be implementing a scheduled tasks system in our product, but we need a couple of extra features.  In the interest of interoperability and not reinventing cron too many times, here are the features that we need, and the database changes that would be required:&lt;br /&gt;
* plugins need to define multiple cron jobs on-the-fly (one of our plugins will allow the user to schedule several tasks with different schedules), and allow plugins to modify those tasks&lt;br /&gt;
* ability to specify that a task should run n times, or until [date]&lt;br /&gt;
&lt;br /&gt;
For the first requirement, I&#039;d like to add a taskcode field to the DB, to allow plugins to identify the different tasks that it creates.  The callfunction would then be called with taskcode as an argument.&lt;br /&gt;
&lt;br /&gt;
For the second requirement, I think that we can roll the onceoff_tasks table into the main tasks table, and just add extra fields for number of times remaining and/or end date.  So onceoff tasks would just be a task with the number of runs remaining set to 1, nextruntime set to the time that it should run, and the cron fields set to (empty? or &amp;quot;*&amp;quot;?).  With the taskcode field, we wouldn&#039;t need the customdata field -- the task can use the taskcode field to identify the task, and load customdata from its own table.&lt;br /&gt;
&lt;br /&gt;
Here is my proposed table, with changes highlighted:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;scheduled_tasks:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|plugintype&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|plugintype - should match the path-style declarations in get_plugin_types (eg question/type, not qtype).  Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|pluginname&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|name of the plugin. Will be null for core tasks.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;taskcode&#039;&#039;&#039; (new)&lt;br /&gt;
|varchar(50)&lt;br /&gt;
|a plugin-specific identifier for the task, used to differentiate between multiple tasks for the same plugin&lt;br /&gt;
|-&lt;br /&gt;
|callfunction&lt;br /&gt;
|varchar(200) &amp;lt;strike&amp;gt;(unique)&amp;lt;/strike&amp;gt;&lt;br /&gt;
|the function to call. &amp;lt;strike&amp;gt;Must be unique, as it will be used for the locking.&amp;lt;/strike&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lastruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|nextruntime&lt;br /&gt;
|int(10)&lt;br /&gt;
|unix timestamp&lt;br /&gt;
|-&lt;br /&gt;
|blocking&lt;br /&gt;
|int(1)&lt;br /&gt;
|0 or 1 - whether this task, when running, blocks everything else from running.&lt;br /&gt;
|-&lt;br /&gt;
|minute&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|hour&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|day&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|month&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|dayofweek&lt;br /&gt;
|varchar(25)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;runsremaining&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Number of times that the task will run&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;enddate&#039;&#039;&#039; (new)&lt;br /&gt;
|integer&lt;br /&gt;
|Task will not run after this date&lt;br /&gt;
|-&lt;br /&gt;
|customised&lt;br /&gt;
|integer(1)&lt;br /&gt;
|0 or 1 - whether this time differs from what is in code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Since we can now have multiple tasks with the same callfunction, we can&#039;t enforce that it be unique.  So we can either use (taskcode,callfunction) or (plugintype,pluginname,taskcode) as the key for locking.&lt;br /&gt;
&lt;br /&gt;
Also, do we need a field to specify which file the callfunction is in?&lt;br /&gt;
&lt;br /&gt;
--[[User:Hubert Chathi|Hubert Chathi]] 14:45, 8 March 2011 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:MNET_2.0&amp;diff=68837</id>
		<title>Development talk:MNET 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:MNET_2.0&amp;diff=68837"/>
		<updated>2010-02-19T15:32:23Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: Just to note, neither the previous or the current implementations of system/methodSignature comply with the xmlrpc introspection spec: http://scripts.incutio.com/xmlrpc/introspection.html ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Just to note, neither the previous or the current implementations of system/methodSignature comply with the xmlrpc introspection spec: http://scripts.incutio.com/xmlrpc/introspection.html  The spec specifies that it returns an array of arrays, where the inner array is simply an array of strings.  Whether we actually care about following the spec is a different matter...  --[[User:Hubert Chathi|Hubert Chathi]] 15:32, 19 February 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67012</id>
		<title>Development:MNet Protocol</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67012"/>
		<updated>2010-01-07T19:36:47Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Security */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Moodle Networks allows other sites to perform RPC calls on a Moodle instance in a secure fashion. (Most) requests are signed and encrypted for security. Sites are identified by their web root ($CFG-&amp;gt;wwwroot in Moodle), and publish a public key (RSA). Requests and responses are encoded using XML-RPC, and signing and encryption are performed using XML-SIG and XML-ENC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Application types ==&lt;br /&gt;
&lt;br /&gt;
* MNet supports different types of applications, with different access URLs&lt;br /&gt;
* defined in mnet_application table&lt;br /&gt;
* lists names and URLs for RPC&lt;br /&gt;
&lt;br /&gt;
== Log in flow ==&lt;br /&gt;
&lt;br /&gt;
* dramatis personae&lt;br /&gt;
** user&lt;br /&gt;
** IdP (identity provider) = site the user is logging in from&lt;br /&gt;
** SP (service provider) = site the user is logging in to&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Basic successful log in ===&lt;br /&gt;
&lt;br /&gt;
# user clicks on link on IdP&lt;br /&gt;
# user is taken to /auth/mnet/jump.php with hostid parameter set to SP&#039;s ID, and (optionally) wantsurl set&lt;br /&gt;
# IdP generates token and creates MNet session (see below)&lt;br /&gt;
# IdP redirects user to SP&#039;s &amp;quot;land&amp;quot; url (as defined in mnet_application table) with token, idp, and wantsurl parameters set&lt;br /&gt;
# user visits SP&#039;s land url&lt;br /&gt;
# SP calls &amp;quot;auth/mnet/auth.php/user_authorise&amp;quot; on IdP via XML-RPC with token and user&#039;s useragent string as parameters&lt;br /&gt;
# IdP verifies MNet session and returns user data&lt;br /&gt;
# SP may fetch additional data from IdP, add user to its own DB, update enrolments on IdP, etc.&lt;br /&gt;
# SP redirects user to wantsurl&lt;br /&gt;
&lt;br /&gt;
== MNet session ==&lt;br /&gt;
&lt;br /&gt;
ID provider stores:&lt;br /&gt;
* host&lt;br /&gt;
* userid&lt;br /&gt;
* username&lt;br /&gt;
* sha1(useragent)&lt;br /&gt;
* token&lt;br /&gt;
* confirm timeout&lt;br /&gt;
* expires&lt;br /&gt;
* session id&lt;br /&gt;
&lt;br /&gt;
== Allowed RPC calls ==&lt;br /&gt;
&lt;br /&gt;
* permissions stored in mnet_host2service x mnet_service2rpc x mnet_rpc (except for &amp;quot;dangerous&amp;quot; calls)&lt;br /&gt;
* modules/plugins must have ($module_)mnet_publishes function&lt;br /&gt;
* system&lt;br /&gt;
** system/listMethods&lt;br /&gt;
** system/methodSignature&lt;br /&gt;
** system/methodHelp&lt;br /&gt;
** system/listServices&lt;br /&gt;
** system/keyswap&lt;br /&gt;
* auth&lt;br /&gt;
** auth/$plugin/auth.php/$method -&amp;gt; file:/auth/$plugin/auth.php class:auth_plugin_$plugin method:$method&lt;br /&gt;
* enrol&lt;br /&gt;
** auth/$plugin/enrol.php/$method -&amp;gt; file:/enrol/$plugin/enrol.php class:enrolment_plugin_$plugin method:$method&lt;br /&gt;
* portfolio (Moodle 2.0)&lt;br /&gt;
** portfolio/$plugin/lib.php/$method -&amp;gt; file:/portfolio/type/$plugin/lib.php class:portfolio_plugin_$plugin method:$method&lt;br /&gt;
* repository (Moodle 2.0)&lt;br /&gt;
** repository/$plugin/repository.class.php/$method -&amp;gt; file:repository/$plugin/repository.class.php class:repository_$plugin method:$method&lt;br /&gt;
* mod&lt;br /&gt;
** mod/$module/rpclib.php/$function -&amp;gt; file:/mod/$module/rpclib.php function:$function&lt;br /&gt;
* dangerous (only if sender has plaintext_is_ok set)&lt;br /&gt;
** dangerous/$path/$function -&amp;gt; file:/$path function:$function (response is not encrypted/signed)&lt;br /&gt;
&lt;br /&gt;
see [[Development:MNet services]] for more information on the default available methods&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
* XML-RPC messages are encrypted/signed using public key cryptography&lt;br /&gt;
* use wrappers based on XML-SEC&lt;br /&gt;
* wrappers have &amp;quot;wwwroot&amp;quot; element to identify the sender&lt;br /&gt;
* Note: security may be compromised by a man-in-the-middle and/or DNS attack&lt;br /&gt;
* see also [[Mnet keys]]&lt;br /&gt;
&lt;br /&gt;
== encryption ==&lt;br /&gt;
&lt;br /&gt;
* uses openssl&#039;s seal routine&lt;br /&gt;
* RC4-encrypted (128-bit key)&lt;br /&gt;
* RC4 key encrypted (RSA) with public key&lt;br /&gt;
&lt;br /&gt;
== signature ==&lt;br /&gt;
&lt;br /&gt;
* digest: SHA-1&lt;br /&gt;
* signature: RSA (despite the XML-SIG wrapper claiming to be DSA)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== key generation ==&lt;br /&gt;
&lt;br /&gt;
* 1024 bit RSA&lt;br /&gt;
* self-signed&lt;br /&gt;
* send certificate as PEM-encoded&lt;br /&gt;
* X.509 certificate fields (only CN is actually checked)&lt;br /&gt;
* C (country name)&lt;br /&gt;
* ST (state or province name)&lt;br /&gt;
* L (locality name)&lt;br /&gt;
* O (organization name)&lt;br /&gt;
* OU (organizational unit name) = Moodle (or whatever software you are running)&lt;br /&gt;
* CN (common name) = $wwwroot (no trailing slashes)&lt;br /&gt;
* EMAILADDRESS (email address)&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
see also [[Development:MNet faults]]&lt;br /&gt;
&lt;br /&gt;
=== if signature does not match ===&lt;br /&gt;
(see also http://moodle.org/mod/forum/discuss.php?d=102113)&lt;br /&gt;
&lt;br /&gt;
* server sends &amp;quot;system/listServices&amp;quot; to client&lt;br /&gt;
* system/listServices is used so that the server will return a (signed) 7025 fault&lt;br /&gt;
* server retrieves key from response&lt;br /&gt;
&lt;br /&gt;
=== if decryption fails ===&lt;br /&gt;
* try decrypting against old keys&lt;br /&gt;
* if able to decrypt, send fault #7025, signed with old private key, with certificate as content. This reduces an attacker&#039;s ability to perform a man-in-the-middle attack.&lt;br /&gt;
* otherwise, send fault #7023&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_faults&amp;diff=67011</id>
		<title>Development:MNet faults</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_faults&amp;diff=67011"/>
		<updated>2010-01-07T19:33:31Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: This page lists XML-RPC faults that may be thrown by Moodle.   == 702/703/706/713/7012/7013/7015/7018/7019 nosuchfunction ==  Why do we need so many error codes for this? (See also 7019 un...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page lists XML-RPC faults that may be thrown by Moodle.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 702/703/706/713/7012/7013/7015/7018/7019 nosuchfunction ==&lt;br /&gt;
&lt;br /&gt;
Why do we need so many error codes for this? (See also 7019 unknownerror)&lt;br /&gt;
&lt;br /&gt;
== 704 nosuchservice ==&lt;br /&gt;
&lt;br /&gt;
The MNet dispatcher mode is set to &amp;quot;off&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== 705 nosuchfile ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 707 forbidden-function ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 709 nosuchpublickey ==&lt;br /&gt;
&lt;br /&gt;
The client doesn&#039;t have a public key set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 710 verifysignature-invalid ==&lt;br /&gt;
&lt;br /&gt;
The signature was invalid.&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 711/7022 verifysignature-error ==&lt;br /&gt;
&lt;br /&gt;
The request was not signed. (711 used in Moodle 2.0 – present in Moodle 1.9, but unreachable) (7022 used in Moodle 1.9, removed in 2.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 712 phperror ==&lt;br /&gt;
&lt;br /&gt;
Some unspecified server-side error occurred (currently only sent when $_SERVER is not set).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7014 nosuchmethod ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7019 unknownerror ==&lt;br /&gt;
&lt;br /&gt;
The permission checking system gave a result that is unknown. (7019 could also be nosuchfunction)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7020 wrong-wwwroot ==&lt;br /&gt;
&lt;br /&gt;
An unknown client tried to send a request.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7021 forbidden-transport ==&lt;br /&gt;
&lt;br /&gt;
An unencrypted request is made that isn&#039;t system/keyswap, and plaintext_is_ok is not set for the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7023 encryption-invalid ==&lt;br /&gt;
&lt;br /&gt;
The server receives an RPC call that cannot be decrypted with the current or any past keys.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7024 payload-not-encrypted ==&lt;br /&gt;
&lt;br /&gt;
Although this is in the code, it doesn&#039;t look like it will ever be called, because it only happens when the server has already determined that the request was encrypted. (See also 7021 forbidden-transport) (Removed in Moodle 2.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 7025 (public key) ==&lt;br /&gt;
&lt;br /&gt;
Sent when the client has encrypted their request using an old key. The faultString is set to the new certificate in PEM format, and it should be signed with the old private key.&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_services&amp;diff=67010</id>
		<title>Development:MNet services</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_services&amp;diff=67010"/>
		<updated>2010-01-07T19:29:36Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: This page lists the services (and methods in that service) that are available to MNet clients. Services are MNet&amp;#039;s way of grouping methods, and allowing MNet sites to publish and/or subscr...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page lists the services (and methods in that service) that are available to MNet clients. Services are MNet&#039;s way of grouping methods, and allowing MNet sites to publish and/or subscribe to services.  The descriptions are not complete.  Please help fill it out!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== System ==&lt;br /&gt;
&lt;br /&gt;
Implemented in /mnet/xmlrpc/server.php, this provides basic information about the MNet server. These methods may also be called as &amp;quot;system.*&amp;quot; in addition to the &amp;quot;system/*&amp;quot; pattern common to the other method names. The system/listMethods, system/methodSignature, and system/methodHelp methods are based on [http://xmlrpc-c.sourceforge.net/introspection.html XML-RPC Introspection].&lt;br /&gt;
&lt;br /&gt;
This service is not returned by system/listServices, nor are any of the methods listed by the XML-RPC Introspection methods.&lt;br /&gt;
&lt;br /&gt;
=== system/listMethods ===&lt;br /&gt;
Lists the available methods.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* service name(string) (optional): If provided, list only the methods provided by the given service. If not specified, list all available methods. (This parameter is not present in XML-RPC Introspection.)&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* array of strings, giving the method names&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
Only lists methods that the client is allowed to execute.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== system/methodSignature ===&lt;br /&gt;
Gives the method signature of the requested method.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* method name(string): The name of the method to provide the method signature for.&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* array, giving the method signature(s). Note: the format is different from the one specified in the XML-RPC Introspection spec.&lt;br /&gt;
** Each array element is itself an array&lt;br /&gt;
*** Each array element is a struct, with fields &amp;quot;type&amp;quot; and &amp;quot;description&amp;quot;, and values being strings.&lt;br /&gt;
*** The first array element represents the return value. Subsequent array elements represent the parameters.&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
If the client is not allowed to execute the method, returns an empty array.&lt;br /&gt;
&lt;br /&gt;
=== system/methodHelp ===&lt;br /&gt;
Give a textual description of the requested method.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* method name(string): The name of the method to provide help for.&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* string, a description of the method.&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
If the client is not allowed to execute the method, returns server fault 7019.&lt;br /&gt;
&lt;br /&gt;
=== system/listServices ===&lt;br /&gt;
List the available services.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
none&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* array, giving the service names, versions, and publish/subscription status. Each array element is a struct with the following keys:&lt;br /&gt;
** name(string): the name of the service&lt;br /&gt;
** apiversion(integer): the API version provided&lt;br /&gt;
** publish(integer): whether the server is publishing this service to the client&lt;br /&gt;
** subscribe(integer): whether the server is subscribing to this service from the client&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
Only services that are published or subscribed are returned.&lt;br /&gt;
&lt;br /&gt;
=== system/keySwap ===&lt;br /&gt;
Swap public keys via X509 certificates.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* wwwroot(string): the client&#039;s wwwroot.&lt;br /&gt;
* certificate(string): the client&#039;s X509 certificate, in PEM format&lt;br /&gt;
* application(string): the application type&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* (string) the server&#039;s X509 certificate, in PEM format&lt;br /&gt;
&lt;br /&gt;
==== Security ====&lt;br /&gt;
This is the only MNet method that can be called from all hosts without encryption and signing (since that is the only way to bootstrap the process).&lt;br /&gt;
&lt;br /&gt;
You really shouldn&#039;t be trusting the client&#039;s parameters, as these can be easily forged. If the certificate differs from the certificate you have stored for the given wwwroot, you should double-check by doing your own system/keySwap call, or trying to send an encrypted and signed XML-RPC request to the client. In this way, a successful attack would require at least DNS hijacking and/or a man-in-the-middle attack, both of which break MNet&#039;s security anyways.&lt;br /&gt;
&lt;br /&gt;
== sso_idp (version 1) ==&lt;br /&gt;
Identity provider for single sign on.&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/user_authorise ===&lt;br /&gt;
(note UK spelling of &amp;quot;authorise&amp;quot;) Return user data for the provided token, compare with user_agent string.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* token(string): token provided by the IdP&lt;br /&gt;
* user agent(string): SHA-1 hash of the user&#039;s user agent string&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* struct, containing the user&#039;s profile data. The fields provided are: username, email, auth (=&amp;quot;mnet&amp;quot;), confirmed, deleted, firstname, lastname, city, country, lang, timezone, description, mailformat, maildigest, maildisplay, htmleditor, wwwroot (the IdP&#039;s wwwroot), session.gc_maxlifetime, picture (integer/boolean), imagehash (if picture != 0; sha1 hash of profile picture file), myhosts (an array describing how many courses the user is enrolled in, in all known hosts)&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/keepalive_server ===&lt;br /&gt;
&amp;quot;Receives an array of usernames from a remote machine and prods their sessions to keep them alive&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* array of usernames&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* struct:&lt;br /&gt;
** if success:&lt;br /&gt;
*** code (int): 0&lt;br /&gt;
*** message (string): &amp;quot;All ok&amp;quot;&lt;br /&gt;
*** last_log_id (int): the ID of the last log entry received from auth/mnet/auth.php/refresh_log&lt;br /&gt;
** if error:&lt;br /&gt;
**** code (int): 1&lt;br /&gt;
**** message (string): &amp;quot;We failed to refresh the session for the following usernames: ...&amp;quot;&lt;br /&gt;
**** last_log_id (int): the ID of the last log entry received from auth/mnet/auth.php/refresh_log&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/kill_children ===&lt;br /&gt;
&amp;quot;The IdP uses this function to kill child sessions on other hosts&amp;quot;&lt;br /&gt;
&lt;br /&gt;
never seems to be called by Moodle networks (called on logout instead)&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/refresh_log ===&lt;br /&gt;
=== auth/mnet/auth.php/fetch_user_image ===&lt;br /&gt;
&amp;quot;Returns the user&#039;s image as a base64 encoded string.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* username (string)&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* false on error, otherwise struct:&lt;br /&gt;
** f1 (string): base64 encoded copy of user&#039;s f1.jpg&lt;br /&gt;
** f2 (string): base64 encoded copy of user&#039;s f2.jpg&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/fetch_theme_info ===&lt;br /&gt;
&amp;quot;Returns the theme information and logo url as strings.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
none&lt;br /&gt;
&lt;br /&gt;
==== Return value ====&lt;br /&gt;
* struct:&lt;br /&gt;
** themename (string)&lt;br /&gt;
** logourl (string): Url for theme logo&lt;br /&gt;
** auth/mnet/auth.php/update_enrolments&lt;br /&gt;
&lt;br /&gt;
== sso_sp (version 1) ==&lt;br /&gt;
Service provider for single sign on.&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/keepalive_client ===&lt;br /&gt;
&amp;quot;Poll the IdP server to let it know that a user it has authenticated is still online&amp;quot; No, I don&#039;t know what that means either.&lt;br /&gt;
&lt;br /&gt;
never seems to be called by Moodle networks (called by cron instead)&lt;br /&gt;
calls auth/mnet/auth.php/keepalive_server on each IdP that has local users logged in&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
none&lt;br /&gt;
&lt;br /&gt;
==== Return Value ====&lt;br /&gt;
none&lt;br /&gt;
&lt;br /&gt;
=== auth/mnet/auth.php/kill_child ===&lt;br /&gt;
Requests that the SP ends the user&#039;s session. Used for single sign off.&lt;br /&gt;
&lt;br /&gt;
==== Parameters ====&lt;br /&gt;
* username(string)&lt;br /&gt;
* useragent(string): SHA-1 hash of the user&#039;s user agent string&lt;br /&gt;
&lt;br /&gt;
Note that the calling IdP is identified through MNet signatures&lt;br /&gt;
&lt;br /&gt;
==== Return Value ====&lt;br /&gt;
* true on success (boolean)&lt;br /&gt;
&lt;br /&gt;
== mnet_enrol (version 1) ==&lt;br /&gt;
Moodle networks enrolments. Enable remote administrators to enrol users in local courses.&lt;br /&gt;
&lt;br /&gt;
=== enrol/mnet/enrol.php/available_courses ===&lt;br /&gt;
=== enrol/mnet/enrol.php/user_enrolments ===&lt;br /&gt;
=== enrol/mnet/enrol.php/enrol_user ===&lt;br /&gt;
=== enrol/mnet/enrol.php/unenrol_user ===&lt;br /&gt;
=== enrol/mnet/enrol.php/course_enrolments ===&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67009</id>
		<title>Development:MNet Protocol</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67009"/>
		<updated>2010-01-07T19:29:24Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Moodle Networks allows other sites to perform RPC calls on a Moodle instance in a secure fashion. (Most) requests are signed and encrypted for security. Sites are identified by their web root ($CFG-&amp;gt;wwwroot in Moodle), and publish a public key (RSA). Requests and responses are encoded using XML-RPC, and signing and encryption are performed using XML-SIG and XML-ENC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Application types ==&lt;br /&gt;
&lt;br /&gt;
* MNet supports different types of applications, with different access URLs&lt;br /&gt;
* defined in mnet_application table&lt;br /&gt;
* lists names and URLs for RPC&lt;br /&gt;
&lt;br /&gt;
== Log in flow ==&lt;br /&gt;
&lt;br /&gt;
* dramatis personae&lt;br /&gt;
** user&lt;br /&gt;
** IdP (identity provider) = site the user is logging in from&lt;br /&gt;
** SP (service provider) = site the user is logging in to&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Basic successful log in ===&lt;br /&gt;
&lt;br /&gt;
# user clicks on link on IdP&lt;br /&gt;
# user is taken to /auth/mnet/jump.php with hostid parameter set to SP&#039;s ID, and (optionally) wantsurl set&lt;br /&gt;
# IdP generates token and creates MNet session (see below)&lt;br /&gt;
# IdP redirects user to SP&#039;s &amp;quot;land&amp;quot; url (as defined in mnet_application table) with token, idp, and wantsurl parameters set&lt;br /&gt;
# user visits SP&#039;s land url&lt;br /&gt;
# SP calls &amp;quot;auth/mnet/auth.php/user_authorise&amp;quot; on IdP via XML-RPC with token and user&#039;s useragent string as parameters&lt;br /&gt;
# IdP verifies MNet session and returns user data&lt;br /&gt;
# SP may fetch additional data from IdP, add user to its own DB, update enrolments on IdP, etc.&lt;br /&gt;
# SP redirects user to wantsurl&lt;br /&gt;
&lt;br /&gt;
== MNet session ==&lt;br /&gt;
&lt;br /&gt;
ID provider stores:&lt;br /&gt;
* host&lt;br /&gt;
* userid&lt;br /&gt;
* username&lt;br /&gt;
* sha1(useragent)&lt;br /&gt;
* token&lt;br /&gt;
* confirm timeout&lt;br /&gt;
* expires&lt;br /&gt;
* session id&lt;br /&gt;
&lt;br /&gt;
== Allowed RPC calls ==&lt;br /&gt;
&lt;br /&gt;
* permissions stored in mnet_host2service x mnet_service2rpc x mnet_rpc (except for &amp;quot;dangerous&amp;quot; calls)&lt;br /&gt;
* modules/plugins must have ($module_)mnet_publishes function&lt;br /&gt;
* system&lt;br /&gt;
** system/listMethods&lt;br /&gt;
** system/methodSignature&lt;br /&gt;
** system/methodHelp&lt;br /&gt;
** system/listServices&lt;br /&gt;
** system/keyswap&lt;br /&gt;
* auth&lt;br /&gt;
** auth/$plugin/auth.php/$method -&amp;gt; file:/auth/$plugin/auth.php class:auth_plugin_$plugin method:$method&lt;br /&gt;
* enrol&lt;br /&gt;
** auth/$plugin/enrol.php/$method -&amp;gt; file:/enrol/$plugin/enrol.php class:enrolment_plugin_$plugin method:$method&lt;br /&gt;
* portfolio (Moodle 2.0)&lt;br /&gt;
** portfolio/$plugin/lib.php/$method -&amp;gt; file:/portfolio/type/$plugin/lib.php class:portfolio_plugin_$plugin method:$method&lt;br /&gt;
* repository (Moodle 2.0)&lt;br /&gt;
** repository/$plugin/repository.class.php/$method -&amp;gt; file:repository/$plugin/repository.class.php class:repository_$plugin method:$method&lt;br /&gt;
* mod&lt;br /&gt;
** mod/$module/rpclib.php/$function -&amp;gt; file:/mod/$module/rpclib.php function:$function&lt;br /&gt;
* dangerous (only if sender has plaintext_is_ok set)&lt;br /&gt;
** dangerous/$path/$function -&amp;gt; file:/$path function:$function (response is not encrypted/signed)&lt;br /&gt;
&lt;br /&gt;
see [[Development:MNet services]] for more information on the default available methods&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
* XML-RPC messages are encrypted/signed using public key cryptography&lt;br /&gt;
* use wrappers based on XML-SEC&lt;br /&gt;
* wrappers have &amp;quot;wwwroot&amp;quot; element to identify the sender&lt;br /&gt;
* Note: security may be compromised by a man-in-the-middle and/or DNS attack&lt;br /&gt;
&lt;br /&gt;
== encryption ==&lt;br /&gt;
&lt;br /&gt;
* uses openssl&#039;s seal routine&lt;br /&gt;
* RC4-encrypted (128-bit key)&lt;br /&gt;
* RC4 key encrypted (RSA) with public key&lt;br /&gt;
&lt;br /&gt;
== signature ==&lt;br /&gt;
&lt;br /&gt;
* digest: SHA-1&lt;br /&gt;
* signature: RSA (despite the XML-SIG wrapper claiming to be DSA)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== key generation ==&lt;br /&gt;
&lt;br /&gt;
* 1024 bit RSA&lt;br /&gt;
* self-signed&lt;br /&gt;
* send certificate as PEM-encoded&lt;br /&gt;
* X.509 certificate fields (only CN is actually checked)&lt;br /&gt;
* C (country name)&lt;br /&gt;
* ST (state or province name)&lt;br /&gt;
* L (locality name)&lt;br /&gt;
* O (organization name)&lt;br /&gt;
* OU (organizational unit name) = Moodle (or whatever software you are running)&lt;br /&gt;
* CN (common name) = $wwwroot (no trailing slashes)&lt;br /&gt;
* EMAILADDRESS (email address)&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
see also [[Development:MNet faults]]&lt;br /&gt;
&lt;br /&gt;
=== if signature does not match ===&lt;br /&gt;
(see also http://moodle.org/mod/forum/discuss.php?d=102113)&lt;br /&gt;
&lt;br /&gt;
* server sends &amp;quot;system/listServices&amp;quot; to client&lt;br /&gt;
* system/listServices is used so that the server will return a (signed) 7025 fault&lt;br /&gt;
* server retrieves key from response&lt;br /&gt;
&lt;br /&gt;
=== if decryption fails ===&lt;br /&gt;
* try decrypting against old keys&lt;br /&gt;
* if able to decrypt, send fault #7025, signed with old private key, with certificate as content. This reduces an attacker&#039;s ability to perform a man-in-the-middle attack.&lt;br /&gt;
* otherwise, send fault #7023&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67006</id>
		<title>Development:MNet Protocol</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67006"/>
		<updated>2010-01-07T19:11:10Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Moodle Networks allows other sites to perform RPC calls on a Moodle instance in a secure fashion. (Most) requests are signed and encrypted for security. Sites are identified by their web root ($CFG-&amp;gt;wwwroot in Moodle), and publish a public key (RSA). Requests and responses are encoded using XML-RPC, and signing and encryption are performed using XML-SIG and XML-ENC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Application types ==&lt;br /&gt;
&lt;br /&gt;
* MNet supports different types of applications, with different access URLs&lt;br /&gt;
* defined in mnet_application table&lt;br /&gt;
* lists names and URLs for RPC&lt;br /&gt;
&lt;br /&gt;
== Log in flow ==&lt;br /&gt;
&lt;br /&gt;
* dramatis personae&lt;br /&gt;
** user&lt;br /&gt;
** IdP (identity provider) = site the user is logging in from&lt;br /&gt;
** SP (service provider) = site the user is logging in to&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Basic successful log in ===&lt;br /&gt;
&lt;br /&gt;
# user clicks on link on IdP&lt;br /&gt;
# user is taken to /auth/mnet/jump.php with hostid parameter set to SP&#039;s ID, and (optionally) wantsurl set&lt;br /&gt;
# IdP generates token and creates MNet session (see below)&lt;br /&gt;
# IdP redirects user to SP&#039;s &amp;quot;land&amp;quot; url (as defined in mnet_application table) with token, idp, and wantsurl parameters set&lt;br /&gt;
# user visits SP&#039;s land url&lt;br /&gt;
# SP calls &amp;quot;auth/mnet/auth.php/user_authorise&amp;quot; on IdP via XML-RPC with token and user&#039;s useragent string as parameters&lt;br /&gt;
# IdP verifies MNet session and returns user data&lt;br /&gt;
# SP may fetch additional data from IdP, add user to its own DB, update enrolments on IdP, etc.&lt;br /&gt;
# SP redirects user to wantsurl&lt;br /&gt;
&lt;br /&gt;
== MNet session ==&lt;br /&gt;
&lt;br /&gt;
ID provider stores:&lt;br /&gt;
* host&lt;br /&gt;
* userid&lt;br /&gt;
* username&lt;br /&gt;
* sha1(useragent)&lt;br /&gt;
* token&lt;br /&gt;
* confirm timeout&lt;br /&gt;
* expires&lt;br /&gt;
* session id&lt;br /&gt;
&lt;br /&gt;
== Allowed RPC calls ==&lt;br /&gt;
&lt;br /&gt;
* permissions stored in mnet_host2service x mnet_service2rpc x mnet_rpc (except for &amp;quot;dangerous&amp;quot; calls)&lt;br /&gt;
* modules/plugins must have ($module_)mnet_publishes function&lt;br /&gt;
* system&lt;br /&gt;
** system/listMethods&lt;br /&gt;
** system/methodSignature&lt;br /&gt;
** system/methodHelp&lt;br /&gt;
** system/listServices&lt;br /&gt;
** system/keyswap&lt;br /&gt;
* auth&lt;br /&gt;
** auth/$plugin/auth.php/$method -&amp;gt; file:/auth/$plugin/auth.php class:auth_plugin_$plugin method:$method&lt;br /&gt;
* enrol&lt;br /&gt;
** auth/$plugin/enrol.php/$method -&amp;gt; file:/enrol/$plugin/enrol.php class:enrolment_plugin_$plugin method:$method&lt;br /&gt;
* portfolio (Moodle 2.0)&lt;br /&gt;
** portfolio/$plugin/lib.php/$method -&amp;gt; file:/portfolio/type/$plugin/lib.php class:portfolio_plugin_$plugin method:$method&lt;br /&gt;
* repository (Moodle 2.0)&lt;br /&gt;
** repository/$plugin/repository.class.php/$method -&amp;gt; file:repository/$plugin/repository.class.php class:repository_$plugin method:$method&lt;br /&gt;
* mod&lt;br /&gt;
** mod/$module/rpclib.php/$function -&amp;gt; file:/mod/$module/rpclib.php function:$function&lt;br /&gt;
* dangerous (only if sender has plaintext_is_ok set)&lt;br /&gt;
** dangerous/$path/$function -&amp;gt; file:/$path function:$function (response is not encrypted/signed)&lt;br /&gt;
&lt;br /&gt;
see [[MNet services]] for more information on the default available methods&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
* XML-RPC messages are encrypted/signed using public key cryptography&lt;br /&gt;
* use wrappers based on XML-SEC&lt;br /&gt;
* wrappers have &amp;quot;wwwroot&amp;quot; element to identify the sender&lt;br /&gt;
* Note: security may be compromised by a man-in-the-middle and/or DNS attack&lt;br /&gt;
&lt;br /&gt;
== encryption ==&lt;br /&gt;
&lt;br /&gt;
* uses openssl&#039;s seal routine&lt;br /&gt;
* RC4-encrypted (128-bit key)&lt;br /&gt;
* RC4 key encrypted (RSA) with public key&lt;br /&gt;
&lt;br /&gt;
== signature ==&lt;br /&gt;
&lt;br /&gt;
* digest: SHA-1&lt;br /&gt;
* signature: RSA (despite the XML-SIG wrapper claiming to be DSA)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== key generation ==&lt;br /&gt;
&lt;br /&gt;
* 1024 bit RSA&lt;br /&gt;
* self-signed&lt;br /&gt;
* send certificate as PEM-encoded&lt;br /&gt;
* X.509 certificate fields (only CN is actually checked)&lt;br /&gt;
* C (country name)&lt;br /&gt;
* ST (state or province name)&lt;br /&gt;
* L (locality name)&lt;br /&gt;
* O (organization name)&lt;br /&gt;
* OU (organizational unit name) = Moodle (or whatever software you are running)&lt;br /&gt;
* CN (common name) = $wwwroot (no trailing slashes)&lt;br /&gt;
* EMAILADDRESS (email address)&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
see also [[MNet faults]]&lt;br /&gt;
&lt;br /&gt;
=== if signature does not match ===&lt;br /&gt;
(see also http://moodle.org/mod/forum/discuss.php?d=102113)&lt;br /&gt;
&lt;br /&gt;
* server sends &amp;quot;system/listServices&amp;quot; to client&lt;br /&gt;
* system/listServices is used so that the server will return a (signed) 7025 fault&lt;br /&gt;
* server retrieves key from response&lt;br /&gt;
&lt;br /&gt;
=== if decryption fails ===&lt;br /&gt;
* try decrypting against old keys&lt;br /&gt;
* if able to decrypt, send fault #7025, signed with old private key, with certificate as content. This reduces an attacker&#039;s ability to perform a man-in-the-middle attack.&lt;br /&gt;
* otherwise, send fault #7023&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67005</id>
		<title>Development:MNet Protocol</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:MNet_Protocol&amp;diff=67005"/>
		<updated>2010-01-07T19:09:55Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: == Overview ==  Moodle Networks allows other sites to perform RPC calls on a Moodle instance in a secure fashion. (Most) requests are signed and encrypted for security. Sites are identifie...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Moodle Networks allows other sites to perform RPC calls on a Moodle instance in a secure fashion. (Most) requests are signed and encrypted for security. Sites are identified by their web root ($CFG-&amp;gt;wwwroot in Moodle), and publish a public key (RSA). Requests and responses are encoded using XML-RPC, and signing and encryption are performed using XML-SIG and XML-ENC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Application types ==&lt;br /&gt;
&lt;br /&gt;
* MNet supports different types of applications, with different access URLs&lt;br /&gt;
* defined in mnet_application table&lt;br /&gt;
* lists names and URLs for RPC&lt;br /&gt;
&lt;br /&gt;
== Log in flow ==&lt;br /&gt;
&lt;br /&gt;
* dramatis personae&lt;br /&gt;
** user&lt;br /&gt;
** IdP (identity provider) = site the user is logging in from&lt;br /&gt;
** SP (service provider) = site the user is logging in to&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Basic successful log in ===&lt;br /&gt;
&lt;br /&gt;
# user clicks on link on IdP&lt;br /&gt;
# user is taken to /auth/mnet/jump.php with hostid parameter set to SP&#039;s ID, and (optionally) wantsurl set&lt;br /&gt;
# IdP generates token and creates MNet session (see below)&lt;br /&gt;
# IdP redirects user to SP&#039;s &amp;quot;land&amp;quot; url (as defined in mnet_application table) with token, idp, and wantsurl parameters set&lt;br /&gt;
# user visits SP&#039;s land url&lt;br /&gt;
# SP calls &amp;quot;auth/mnet/auth.php/user_authorise&amp;quot; on IdP via XML-RPC with token and user&#039;s useragent string as parameters&lt;br /&gt;
# IdP verifies MNet session and returns user data&lt;br /&gt;
# SP may fetch additional data from IdP, add user to its own DB, update enrolments on IdP, etc.&lt;br /&gt;
# SP redirects user to wantsurl&lt;br /&gt;
&lt;br /&gt;
== MNet session ==&lt;br /&gt;
&lt;br /&gt;
ID provider stores:&lt;br /&gt;
* host&lt;br /&gt;
* userid&lt;br /&gt;
* username&lt;br /&gt;
* sha1(useragent)&lt;br /&gt;
* token&lt;br /&gt;
* confirm timeout&lt;br /&gt;
* expires&lt;br /&gt;
* session id&lt;br /&gt;
&lt;br /&gt;
== Allowed RPC calls ==&lt;br /&gt;
&lt;br /&gt;
* permissions stored in mnet_host2service x mnet_service2rpc x mnet_rpc (except for &amp;quot;dangerous&amp;quot; calls)&lt;br /&gt;
* modules/plugins must have ($module_)mnet_publishes function&lt;br /&gt;
* system&lt;br /&gt;
** system/listMethods&lt;br /&gt;
** system/methodSignature&lt;br /&gt;
** system/methodHelp&lt;br /&gt;
** system/listServices&lt;br /&gt;
** system/keyswap&lt;br /&gt;
* auth&lt;br /&gt;
** auth/$plugin/auth.php/$method -&amp;gt; file:/auth/$plugin/auth.php class:auth_plugin_$plugin method:$method&lt;br /&gt;
* enrol&lt;br /&gt;
** auth/$plugin/enrol.php/$method -&amp;gt; file:/enrol/$plugin/enrol.php class:enrolment_plugin_$plugin method:$method&lt;br /&gt;
* portfolio (Moodle 2.0)&lt;br /&gt;
** portfolio/$plugin/lib.php/$method -&amp;gt; file:/portfolio/type/$plugin/lib.php class:portfolio_plugin_$plugin method:$method&lt;br /&gt;
* repository (Moodle 2.0)&lt;br /&gt;
** repository/$plugin/repository.class.php/$method -&amp;gt; file:repository/$plugin/repository.class.php class:repository_$plugin method:$method&lt;br /&gt;
* mod&lt;br /&gt;
** mod/$module/rpclib.php/$function -&amp;gt; file:/mod/$module/rpclib.php function:$function&lt;br /&gt;
* dangerous (only if sender has plaintext_is_ok set)&lt;br /&gt;
** dangerous/$path/$function -&amp;gt; file:/$path function:$function (response is not encrypted/signed)&lt;br /&gt;
&lt;br /&gt;
see [[MNet services]] for more information on the default available methods&lt;br /&gt;
&lt;br /&gt;
== Security ==&lt;br /&gt;
&lt;br /&gt;
* XML-RPC messages are encrypted/signed using public key cryptography&lt;br /&gt;
* use wrappers based on XML-SEC&lt;br /&gt;
* wrappers have &amp;quot;wwwroot&amp;quot; element to identify the sender&lt;br /&gt;
* Note: security may be compromised by a man-in-the-middle and/or DNS attack&lt;br /&gt;
&lt;br /&gt;
== encryption ==&lt;br /&gt;
&lt;br /&gt;
* uses openssl&#039;s seal routine&lt;br /&gt;
* RC4-encrypted (128-bit key)&lt;br /&gt;
* RC4 key encrypted (RSA) with public key&lt;br /&gt;
&lt;br /&gt;
== signature ==&lt;br /&gt;
&lt;br /&gt;
* digest: SHA-1&lt;br /&gt;
* signature: RSA (despite the XML-SIG wrapper claiming to be DSA)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== key generation ==&lt;br /&gt;
&lt;br /&gt;
* 1024 bit RSA&lt;br /&gt;
* self-signed&lt;br /&gt;
* send certificate as PEM-encoded&lt;br /&gt;
* X.509 certificate fields (only CN is actually checked)&lt;br /&gt;
* C (country name)&lt;br /&gt;
* ST (state or province name)&lt;br /&gt;
* L (locality name)&lt;br /&gt;
* O (organization name)&lt;br /&gt;
* OU (organizational unit name) = Moodle (or whatever software you are running)&lt;br /&gt;
* CN (common name) = $wwwroot (no trailing slashes)&lt;br /&gt;
* EMAILADDRESS (email address)&lt;br /&gt;
&lt;br /&gt;
== Error handling ==&lt;br /&gt;
&lt;br /&gt;
see also [[MNet faults]]&lt;br /&gt;
&lt;br /&gt;
=== if signature does not match ===&lt;br /&gt;
(see also http://moodle.org/mod/forum/discuss.php?d=102113)&lt;br /&gt;
&lt;br /&gt;
* server sends &amp;quot;system/listServices&amp;quot; to client&lt;br /&gt;
* system/listServices is used so that the server will return a (signed) 7025 fault&lt;br /&gt;
* server retrieves key from response&lt;br /&gt;
&lt;br /&gt;
=== if decryption fails ===&lt;br /&gt;
* try decrypting against old keys&lt;br /&gt;
* if able to decrypt, send fault #7025, signed with old private key, with certificate as content. This reduces an attacker&#039;s ability to perform a man-in-the-middle attack.&lt;br /&gt;
* otherwise, send fault #7023&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:MNet_Roadmap&amp;diff=66932</id>
		<title>Development talk:MNet Roadmap</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:MNet_Roadmap&amp;diff=66932"/>
		<updated>2010-01-06T22:23:11Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* What Hubert Hates about MNet (part 1) */ new section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I think the application2service table is a good idea (no more Mahara &amp;quot;course enrolments&amp;quot;!). But I don&#039;t like the idea that the URL field is in this table. Even though it varies by application, it doesn&#039;t apply to _every_ service, and therefore is redundant much of the time. Furthermore, if more services are added that need their own custom per-application fields, all of a sudden this table is getting very big with a lot of poorly related fields.&lt;br /&gt;
&lt;br /&gt;
A different model that doesn&#039;t suffer the problem is this:&lt;br /&gt;
&lt;br /&gt;
==== application2service ====&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|applicationid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_application&lt;br /&gt;
|-&lt;br /&gt;
|serviceid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to mnet_service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== application2service_sso ====&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Datatype&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Comment&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|id&lt;br /&gt;
|integer&lt;br /&gt;
|sequence&lt;br /&gt;
|-&lt;br /&gt;
|a2sid&lt;br /&gt;
|integer&lt;br /&gt;
|fk to application2service(id)&lt;br /&gt;
|-&lt;br /&gt;
|url&lt;br /&gt;
|char(255)&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[User:Nigel McNie|Nigel McNie]] 06:41, 22 July 2008 (CDT)&lt;br /&gt;
&lt;br /&gt;
== What Hubert Hates about MNet (part 1) ==&lt;br /&gt;
&lt;br /&gt;
* (trivial) 28-day key expiry is too short, IMHO.  My own preference would be something on the order of 1 year.&lt;br /&gt;
* (easy) Inconsistent fault codes: when MNet encounters an error, it throws an XMLRPC fault with a seemingly random fault code.  Some fault codes are used for multiple types of errors, and some errors are represented by multiple possible fault codes.&lt;br /&gt;
* (hard) XML-SEC envelopes bloat XMLRPC messages by a lot.  Personally, if I were to design MNet from scratch, I think I would either use HTTP headers, or multipart to send the signature and encryption key.  Obviously, this would be a backward-incompatible protocol change, and we would need to support both protocols in new code.  Someone will have to decide if this is worth the fuss.  I&#039;m not expecting this to be addressed any time soon, but I just wanted to throw this out there and see what other people think.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Split between xmlrpc functions offered and xmlrpc functions available&amp;quot; mentioned in Penny&#039;s changes is also something that I&#039;d like to see fixed.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all I can think of for now.  I&#039;ll add more when I remember more.  --[[User:Hubert Chathi|Hubert Chathi]] 22:23, 6 January 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=66525</id>
		<title>Development:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=66525"/>
		<updated>2009-12-15T17:08:55Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Goals==&lt;br /&gt;
To make the &amp;quot;My Moodle&amp;quot; interface a more usable space that provides each user with their own personal experience. The page should be a user&#039;s personal portal page in Moodle. My Moodle will be the place where information that is user-centric rather than course-centric will be displayed.&lt;br /&gt;
&lt;br /&gt;
Portions of the My Moodle interface should be able to be made customizable by the individual users. Other portions should be able to be locked to certain roles.&lt;br /&gt;
&lt;br /&gt;
It&#039;s also the place where you change your preferences and settings.&lt;br /&gt;
&lt;br /&gt;
It should utilize current Moodle constructs such as blocks, themes and pages.&lt;br /&gt;
&lt;br /&gt;
The user&#039;s profile page should be able to be configured by the user to allow choice of what can be displayed. This also should be manageable at the admin level.&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
* Subpages (Canvases): &lt;br /&gt;
** Tabs in the diagram (navigation style themeable?). &lt;br /&gt;
** Should come with pre-defined pages for:&lt;br /&gt;
*** profile, &lt;br /&gt;
*** course list, &lt;br /&gt;
*** blog ,&lt;br /&gt;
*** reports,&lt;br /&gt;
*** home page / dashboard. &lt;br /&gt;
** Page can define whether blocks can be moved.&lt;br /&gt;
** Possibility for plug-in pages.&lt;br /&gt;
** Possibility for user added pages / canvases.&lt;br /&gt;
** Access to pages should be available – requires context (maybe implement later).&lt;br /&gt;
** Capabilities should be available – that is, standard pages may or may not be configurable to given roles.&lt;br /&gt;
* Blocks: &lt;br /&gt;
** Like normal blocks. &lt;br /&gt;
** Whether or not they can be visible on My Moodle should be configurable. &lt;br /&gt;
** Some should be able to be added, moved and configured by any user.&lt;br /&gt;
** Need to able to be displayed in middle portion.&lt;br /&gt;
** Possible to define valid subpages they can be on&lt;br /&gt;
&lt;br /&gt;
==Solutions==&lt;br /&gt;
&lt;br /&gt;
Review drawings in MDL-19124 for ideas of how this could look.&lt;br /&gt;
&lt;br /&gt;
===Subpages===&lt;br /&gt;
(Consider calling these &amp;quot;canvases&amp;quot; instead of subpages)&lt;br /&gt;
&lt;br /&gt;
These are the actual pages that can contain the functions and blocks in the My Moodle interface. In the referred drawings, each of these would be a tab.&lt;br /&gt;
&lt;br /&gt;
Each of these is a canvas that can be painted with blocks. The blocks would need to know which page they belonged to. By using blocks, issues such as the way a page looks, or the way information is ordered on a page, becomes an issue associated with the block and not with My Moodle itself.&lt;br /&gt;
&lt;br /&gt;
Initially, My Moodle could come with specific pages:&lt;br /&gt;
* home page / dashboard - A completely user configurable page where the informational blocks can be added and moved. User could have items such as news-feeds, calendars, etc.&lt;br /&gt;
* profile - The same function that currently exists on the user profile page. If allowed on the site, provide options for the user to assign what information can be visible by what roles.&lt;br /&gt;
* blog - Access to the user&#039;s blog (like the current tab on the user profile page).&lt;br /&gt;
* course list - A better version of the current My Moodle page.&lt;br /&gt;
* report - Access to various reports and logs on your activities.&lt;br /&gt;
&lt;br /&gt;
Each page would be available to be enabled or disabled to the My Moodle interface.&lt;br /&gt;
&lt;br /&gt;
====Further Expansion====&lt;br /&gt;
Adding a level of pluggability for subpages or canvasses would create an even more configurable experience for the user. Subpage plug-ins could be made available by simply dropping in a standard file layout into a My Moodle subdirectory, like reports. Even more could be provided by allowing users to create new instances of blank pages for their own My Moodle that they could then configure in any way they want.&lt;br /&gt;
&lt;br /&gt;
This will add the extra burden of maintaining a page table per user to track whatever pages have been added to My Moodle for each user.&lt;br /&gt;
&lt;br /&gt;
Subpages will require contexts, so that roles can be given different capabilities (CONTEXT_MYPAGE ?). (These could be extended contexts as described here: MDL-20045). Capabilities would allow some pages to be re-configured by certain roles and not others. This would allow administrators to set up &#039;locked&#039; pages that would always be the same layout for all users.&lt;br /&gt;
&lt;br /&gt;
===Blocks===&lt;br /&gt;
Any of the content on a My Moodle page should be able to be handled with blocks. The positioning of them is what is important.&lt;br /&gt;
&lt;br /&gt;
My Moodle will add a &#039;content&#039; region to display the centre block area.&lt;br /&gt;
&lt;br /&gt;
Blocks should be able to specify whether they are eligible for &amp;quot;My Moodle&amp;quot; inclusion (through applicable_formats method). Additionally, they should be configurable to be eligible for specific sub-pages (this may be possible through the same function). &#039;&#039;&#039;&#039;&#039;Should this also be an administrative function?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Technical Plans==&lt;br /&gt;
* three types of pages: &amp;quot;dashboard&amp;quot;, &amp;quot;public profile&amp;quot;, and &amp;quot;course profile&amp;quot;&lt;br /&gt;
* use navigation block instead of tabs&lt;br /&gt;
&lt;br /&gt;
===dashboard pages===&lt;br /&gt;
* /my/index.php&lt;br /&gt;
* only users can see their own&lt;br /&gt;
* users can customize freely&lt;br /&gt;
* users can add their own pages&lt;br /&gt;
* link to page for changing settings (in settings block)&lt;br /&gt;
* admin can define default blocks that users can remove&lt;br /&gt;
&lt;br /&gt;
===public profile pages===&lt;br /&gt;
* /user/profile.php&lt;br /&gt;
* everyone can see everyone&#039;s profile&lt;br /&gt;
* admin can define blocks that are always seen&lt;br /&gt;
** users cannot delete these blocks&lt;br /&gt;
* users can add new blocks (if they have the capability)&lt;br /&gt;
&lt;br /&gt;
===course profile===&lt;br /&gt;
* /user/view.php&lt;br /&gt;
* picture, description, general information, private information (only displayed to teachers)&lt;br /&gt;
* link to full public profile&lt;br /&gt;
** controlled by code (no editing by any users)&lt;br /&gt;
&lt;br /&gt;
===Other considerations===&lt;br /&gt;
* block permissions&lt;br /&gt;
** change accesslib to add role to user when in their own user context&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* MDL-19124 My Moodle Functional Overhaul&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=122919 New Tracker Item for My Moodle 2.0 Improvements]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=135191 Forum discussion for this page]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:Czech_Hackfest_2009&amp;diff=66339</id>
		<title>Development:Czech Hackfest 2009</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:Czech_Hackfest_2009&amp;diff=66339"/>
		<updated>2009-12-07T07:27:05Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== See also ==&lt;br /&gt;
&lt;br /&gt;
* [http://dev.moodle.org/course/view.php?id=5 Moodle Hackfest 2009] online course&lt;br /&gt;
* Tag #moodledev09&lt;br /&gt;
&lt;br /&gt;
== Programme ==&lt;br /&gt;
&lt;br /&gt;
; Saturday 5th December 2009 :&lt;br /&gt;
&lt;br /&gt;
* Meet each others in Prague (some arrive, some may be there already)&lt;br /&gt;
* Settle down in a hotel - Andel&#039;s hotel - [http://www.andelshotel.com], rooms booked&lt;br /&gt;
* Explore Prague (Castle, Chrles bridge, old town square, etc.)&lt;br /&gt;
* Social beer event&lt;br /&gt;
&lt;br /&gt;
; Sunday 6th December 2009 :&lt;br /&gt;
* Leaving Prague at 10:30 together by a rented micro-bus (about 120 mins)&lt;br /&gt;
* Lunch at [http://www.jested.cz Jested, Liberec] or in Liberec.&lt;br /&gt;
* Moving to the mountains (by bus or car or foot ;-), according to snow conditions)&lt;br /&gt;
* Accommodating at [http://www.dudovi.cz/jizerka/eng/ubytovani.htm Jizerka] ( [http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=jizerka&amp;amp;sll=50.82524,15.428925&amp;amp;sspn=0.298851,0.467606&amp;amp;ie=UTF8&amp;amp;t=h&amp;amp;hq=&amp;amp;hnear=Kořenov-Jizerka,+Czech+Republic&amp;amp;ll=50.822313,15.329361&amp;amp;spn=0.149435,0.233803&amp;amp;z=13 Google Maps] )&lt;br /&gt;
&lt;br /&gt;
; Monday 7th - Thursday 10th December 2009&lt;br /&gt;
* [https://spreadsheets.google.com/ccc?key=0AmamVlPpCnn4dFZyOUJrRjczQnBoUTFSYks5bnFJcHc&amp;amp;hl=en Sessions timetable]&lt;br /&gt;
&lt;br /&gt;
; Friday 11th December 2009 &lt;br /&gt;
* moving back to Prague on Friday&lt;br /&gt;
* more Prague sightseeing&lt;br /&gt;
* - Andel&#039;s hotel - [http://www.andelshotel.com], rooms booked&lt;br /&gt;
* official end of hackfest&lt;br /&gt;
&lt;br /&gt;
== Things to discuss ==&lt;br /&gt;
&lt;br /&gt;
===Big (~3 hours)===&lt;br /&gt;
* Moodle 3.0&lt;br /&gt;
* Testing / QA&lt;br /&gt;
* Backup and restore&lt;br /&gt;
* [[Development:Languages]]&lt;br /&gt;
* Roles / Enrolments /Site-wide groups&lt;br /&gt;
&lt;br /&gt;
===Medium (~2 hours)===&lt;br /&gt;
* Moodle 2.0&lt;br /&gt;
* My Moodle + User profiles&lt;br /&gt;
* Wiki 2.0&lt;br /&gt;
* Editors / Files&lt;br /&gt;
* Questionnaire / Feedback&lt;br /&gt;
&lt;br /&gt;
===Small (~1 hour)===&lt;br /&gt;
* Moodle 2.1&lt;br /&gt;
* Gradebook&lt;br /&gt;
* Performance / Cron etc&lt;br /&gt;
* Portfolios&lt;br /&gt;
* Anonymous users&lt;br /&gt;
* MNET&lt;br /&gt;
* Workshop module demo&lt;br /&gt;
* Question bank&lt;br /&gt;
&lt;br /&gt;
== Attendees ==&lt;br /&gt;
&lt;br /&gt;
In chaotic order:&lt;br /&gt;
&lt;br /&gt;
# [http://moodle.org/user/view.php?id=1&amp;amp;course=1 Martin Dougiamas]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=3176&amp;amp;course=1 Eloy Lafuente]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=12863&amp;amp;course=1 Petr Skoda]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=93821&amp;amp;course=1 Tim Hunt]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=24152&amp;amp;course=1 Helen Foster]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=17383&amp;amp;course=1 Penny Leach]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=104159&amp;amp;course=1 Dan Poltawski]&lt;br /&gt;
# [http://moodle.org/user/view.php?id=1601&amp;amp;course=1 David Mudrak]&lt;br /&gt;
# Shane Elliott&lt;br /&gt;
# Chris Roy&lt;br /&gt;
# Brian King&lt;br /&gt;
# [http://moodle.org/user/view.php?id=76222&amp;amp;course=1 Daniele Cordella]&lt;br /&gt;
# Mike Churchward&lt;br /&gt;
# [http://moodle.org/user/view.php?id=706541&amp;amp;course=1 Hubert Chathi]&lt;br /&gt;
# Matt Oquist&lt;br /&gt;
# Kris Stokking&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Development talk:Languages]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=64989</id>
		<title>Development:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=64989"/>
		<updated>2009-11-06T17:50:17Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Questions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Goals==&lt;br /&gt;
To make the &amp;quot;My Moodle&amp;quot; interface a more usable space that provides each user with their own personal experience. The page should be a user&#039;s personal portal page in Moodle. My Moodle will be the place where information that is user-centric rather than course-centric will be displayed.&lt;br /&gt;
&lt;br /&gt;
Portions of the My Moodle interface should be able to be made customizable by the individual users. Other portions should be able to be locked to certain roles.&lt;br /&gt;
&lt;br /&gt;
It&#039;s also the place where you change your preferences and settings.&lt;br /&gt;
&lt;br /&gt;
It should utilize current Moodle constructs such as blocks, themes and pages.&lt;br /&gt;
&lt;br /&gt;
The user&#039;s profile page should be able to be configured by the user to allow choice of what can be displayed. This also should be manageable at the admin level.&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
* Subpages (Canvases): &lt;br /&gt;
** Tabs in the diagram (navigation style themeable?). &lt;br /&gt;
** Should come with pre-defined pages for:&lt;br /&gt;
*** profile, &lt;br /&gt;
*** course list, &lt;br /&gt;
*** blog ,&lt;br /&gt;
*** reports,&lt;br /&gt;
*** home page / dashboard. &lt;br /&gt;
** Page can define whether blocks can be moved.&lt;br /&gt;
** Possibility for plug-in pages.&lt;br /&gt;
** Possibility for user added pages / canvases.&lt;br /&gt;
** Access to pages should be available – requires context (maybe implement later).&lt;br /&gt;
** Capabilities should be available – that is, standard pages may or may not be configurable to given roles.&lt;br /&gt;
* Blocks: &lt;br /&gt;
** Like normal blocks. &lt;br /&gt;
** Whether or not they can be visible on My Moodle should be configurable. &lt;br /&gt;
** Some should be able to be added, moved and configured by any user.&lt;br /&gt;
** Need to able to be displayed in middle portion.&lt;br /&gt;
** Possible to define valid subpages they can be on&lt;br /&gt;
&lt;br /&gt;
==Solutions==&lt;br /&gt;
&lt;br /&gt;
Review drawings in MDL-19124 for ideas of how this could look.&lt;br /&gt;
&lt;br /&gt;
===Subpages===&lt;br /&gt;
(Consider calling these &amp;quot;canvases&amp;quot; instead of subpages)&lt;br /&gt;
&lt;br /&gt;
These are the actual pages that can contain the functions and blocks in the My Moodle interface. In the referred drawings, each of these would be a tab.&lt;br /&gt;
&lt;br /&gt;
Each of these is a canvas that can be painted with blocks. The blocks would need to know which page they belonged to. By using blocks, issues such as the way a page looks, or the way information is ordered on a page, becomes an issue associated with the block and not with My Moodle itself.&lt;br /&gt;
&lt;br /&gt;
Initially, My Moodle could come with specific pages:&lt;br /&gt;
* home page / dashboard - A completely user configurable page where the informational blocks can be added and moved. User could have items such as news-feeds, calendars, etc.&lt;br /&gt;
* profile - The same function that currently exists on the user profile page. If allowed on the site, provide options for the user to assign what information can be visible by what roles.&lt;br /&gt;
* blog - Access to the user&#039;s blog (like the current tab on the user profile page).&lt;br /&gt;
* course list - A better version of the current My Moodle page.&lt;br /&gt;
* report - Access to various reports and logs on your activities.&lt;br /&gt;
&lt;br /&gt;
Each page would be available to be enabled or disabled to the My Moodle interface.&lt;br /&gt;
&lt;br /&gt;
====Further Expansion====&lt;br /&gt;
Adding a level of pluggability for subpages or canvasses would create an even more configurable experience for the user. Subpage plug-ins could be made available by simply dropping in a standard file layout into a My Moodle subdirectory, like reports. Even more could be provided by allowing users to create new instances of blank pages for their own My Moodle that they could then configure in any way they want.&lt;br /&gt;
&lt;br /&gt;
This will add the extra burden of maintaining a page table per user to track whatever pages have been added to My Moodle for each user.&lt;br /&gt;
&lt;br /&gt;
Subpages will require contexts, so that roles can be given different capabilities (CONTEXT_MYPAGE ?). (These could be extended contexts as described here: MDL-20045). Capabilities would allow some pages to be re-configured by certain roles and not others. This would allow administrators to set up &#039;locked&#039; pages that would always be the same layout for all users.&lt;br /&gt;
&lt;br /&gt;
===Blocks===&lt;br /&gt;
Any of the content on a My Moodle page should be able to be handled with blocks. The positioning of them is what is important.&lt;br /&gt;
&lt;br /&gt;
My Moodle will add a &#039;content&#039; region to display the centre block area.&lt;br /&gt;
&lt;br /&gt;
Blocks should be able to specify whether they are eligible for &amp;quot;My Moodle&amp;quot; inclusion (through applicable_formats method). Additionally, they should be configurable to be eligible for specific sub-pages (this may be possible through the same function). &#039;&#039;&#039;&#039;&#039;Should this also be an administrative function?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Technical Plans==&lt;br /&gt;
* allow users to see other users&#039; My Moodle pages (subject to access control -- see below)&lt;br /&gt;
&lt;br /&gt;
===Blocks===&lt;br /&gt;
* mdl_block_instances database entry&lt;br /&gt;
** blocks on a specific user&#039;s page, in a specific place: parentcontextid=user&#039;s context ID; showinsubcontexts=0; pagetypepattern=&amp;quot;my-index&amp;quot;; subpagepattern=canvas name; defaultregion=side-pre/content/side-post&lt;br /&gt;
** block on all user&#039;s pages: parentcontextid=1 (system context); showinsubcontexts=0; pagetypepattern=&amp;quot;my-index&amp;quot;; subpagepattern=canvas name; defaultregion=side-pre/content/side-post&lt;br /&gt;
* blocks may choose to display different content/different layout depending on what region they are in (e.g. if they are in the &amp;quot;content&amp;quot; region, vs. one of the side regions)&lt;br /&gt;
** The region that a block is in can be obtained by $this-&amp;gt;instance-&amp;gt;region (is this the best way to find this out, or should there be an API call?)&lt;br /&gt;
* blocks can know which user&#039;s My Moodle page is being viewed through $PAGE-&amp;gt;context.&lt;br /&gt;
&lt;br /&gt;
===Subpages===&lt;br /&gt;
* need a new database table: &amp;quot;mdl_my_subpages&amp;quot;(?) that stores&lt;br /&gt;
** user ID of the subpage owner (or 0 for site-wide pages)&lt;br /&gt;
** page name&lt;br /&gt;
** private/public&lt;br /&gt;
** locked? (for site-wide pages only)&lt;br /&gt;
* start with a set of predefined subpages&lt;br /&gt;
** user profile&lt;br /&gt;
** my course list (the current My Moodle contents)&lt;br /&gt;
* NEED: some way of (optionally) doing localization for names of site-wide pages (e.g. profile page)&lt;br /&gt;
&lt;br /&gt;
===Access control===&lt;br /&gt;
* users can access other users&#039; public pages&lt;br /&gt;
* users with &amp;quot;moodle/my:viewprivatesubpages&amp;quot;(?) capability in the user&#039;s context can view the other user&#039;s private pages&lt;br /&gt;
* users can add/edit their own subpages if they have &amp;quot;moodle/my:manageblocks&amp;quot;&lt;br /&gt;
* users can add/edit other users&#039; subpages if they have &amp;quot;moodle/block:edit&amp;quot; ( or a My Moodle-specific capability?) in the user&#039;s context&lt;br /&gt;
* users can add/edit site-wide pages if they have &amp;quot;moodle/my:editsitewidesubpages&amp;quot;(?) in the system context&lt;br /&gt;
&lt;br /&gt;
===Questions===&lt;br /&gt;
* what happens when a user creates a subpage with the same name as a site-wide page?&lt;br /&gt;
** disallow this? (problems with: site-wide page created after a user creates their page)&lt;br /&gt;
** display both tabs separately? (prefix site-wide page names to prevent subpage name collisions?)&lt;br /&gt;
** &amp;quot;merge&amp;quot; contents? (could this present a spoofing vulnerability?)&lt;br /&gt;
** only allow admins to create supbages? (limiting, but might be OK as a first cut)&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* MDL-19124 My Moodle Functional Overhaul&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=122919 New Tracker Item for My Moodle 2.0 Improvements]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=135191 Forum discussion for this page]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=64943</id>
		<title>Development:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development:My_Moodle_2.0&amp;diff=64943"/>
		<updated>2009-11-05T21:35:14Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Goals==&lt;br /&gt;
To make the &amp;quot;My Moodle&amp;quot; interface a more usable space that provides each user with their own personal experience. The page should be a user&#039;s personal portal page in Moodle. My Moodle will be the place where information that is user-centric rather than course-centric will be displayed.&lt;br /&gt;
&lt;br /&gt;
Portions of the My Moodle interface should be able to be made customizable by the individual users. Other portions should be able to be locked to certain roles.&lt;br /&gt;
&lt;br /&gt;
It&#039;s also the place where you change your preferences and settings.&lt;br /&gt;
&lt;br /&gt;
It should utilize current Moodle constructs such as blocks, themes and pages.&lt;br /&gt;
&lt;br /&gt;
The user&#039;s profile page should be able to be configured by the user to allow choice of what can be displayed. This also should be manageable at the admin level.&lt;br /&gt;
&lt;br /&gt;
==Scope==&lt;br /&gt;
* Subpages (Canvases): &lt;br /&gt;
** Tabs in the diagram (navigation style themeable?). &lt;br /&gt;
** Should come with pre-defined pages for:&lt;br /&gt;
*** profile, &lt;br /&gt;
*** course list, &lt;br /&gt;
*** blog ,&lt;br /&gt;
*** reports,&lt;br /&gt;
*** home page / dashboard. &lt;br /&gt;
** Page can define whether blocks can be moved.&lt;br /&gt;
** Possibility for plug-in pages.&lt;br /&gt;
** Possibility for user added pages / canvases.&lt;br /&gt;
** Access to pages should be available – requires context (maybe implement later).&lt;br /&gt;
** Capabilities should be available – that is, standard pages may or may not be configurable to given roles.&lt;br /&gt;
* Blocks: &lt;br /&gt;
** Like normal blocks. &lt;br /&gt;
** Whether or not they can be visible on My Moodle should be configurable. &lt;br /&gt;
** Some should be able to be added, moved and configured by any user.&lt;br /&gt;
** Need to able to be displayed in middle portion.&lt;br /&gt;
** Possible to define valid subpages they can be on&lt;br /&gt;
&lt;br /&gt;
==Solutions==&lt;br /&gt;
&lt;br /&gt;
Review drawings in MDL-19124 for ideas of how this could look.&lt;br /&gt;
&lt;br /&gt;
===Subpages===&lt;br /&gt;
(Consider calling these &amp;quot;canvases&amp;quot; instead of subpages)&lt;br /&gt;
&lt;br /&gt;
These are the actual pages that can contain the functions and blocks in the My Moodle interface. In the referred drawings, each of these would be a tab.&lt;br /&gt;
&lt;br /&gt;
Each of these is a canvas that can be painted with blocks. The blocks would need to know which page they belonged to. By using blocks, issues such as the way a page looks, or the way information is ordered on a page, becomes an issue associated with the block and not with My Moodle itself.&lt;br /&gt;
&lt;br /&gt;
Initially, My Moodle could come with specific pages:&lt;br /&gt;
* home page / dashboard - A completely user configurable page where the informational blocks can be added and moved. User could have items such as news-feeds, calendars, etc.&lt;br /&gt;
* profile - The same function that currently exists on the user profile page. If allowed on the site, provide options for the user to assign what information can be visible by what roles.&lt;br /&gt;
* blog - Access to the user&#039;s blog (like the current tab on the user profile page).&lt;br /&gt;
* course list - A better version of the current My Moodle page.&lt;br /&gt;
* report - Access to various reports and logs on your activities.&lt;br /&gt;
&lt;br /&gt;
Each page would be available to be enabled or disabled to the My Moodle interface.&lt;br /&gt;
&lt;br /&gt;
====Further Expansion====&lt;br /&gt;
Adding a level of pluggability for subpages or canvasses would create an even more configurable experience for the user. Subpage plug-ins could be made available by simply dropping in a standard file layout into a My Moodle subdirectory, like reports. Even more could be provided by allowing users to create new instances of blank pages for their own My Moodle that they could then configure in any way they want.&lt;br /&gt;
&lt;br /&gt;
This will add the extra burden of maintaining a page table per user to track whatever pages have been added to My Moodle for each user.&lt;br /&gt;
&lt;br /&gt;
Subpages will require contexts, so that roles can be given different capabilities (CONTEXT_MYPAGE ?). (These could be extended contexts as described here: MDL-20045). Capabilities would allow some pages to be re-configured by certain roles and not others. This would allow administrators to set up &#039;locked&#039; pages that would always be the same layout for all users.&lt;br /&gt;
&lt;br /&gt;
===Blocks===&lt;br /&gt;
Any of the content on a My Moodle page should be able to be handled with blocks. The positioning of them is what is important.&lt;br /&gt;
&lt;br /&gt;
My Moodle will add a &#039;content&#039; region to display the centre block area.&lt;br /&gt;
&lt;br /&gt;
Blocks should be able to specify whether they are eligible for &amp;quot;My Moodle&amp;quot; inclusion (through applicable_formats method). Additionally, they should be configurable to be eligible for specific sub-pages (this may be possible through the same function). &#039;&#039;&#039;&#039;&#039;Should this also be an administrative function?&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Technical Plans==&lt;br /&gt;
* allow users to see other users&#039; My Moodle pages (subject to access control -- see below)&lt;br /&gt;
&lt;br /&gt;
===Blocks===&lt;br /&gt;
* mdl_block_instances database entry&lt;br /&gt;
** blocks on a specific user&#039;s page, in a specific place: parentcontextid=user&#039;s context ID; showinsubcontexts=0; pagetypepattern=&amp;quot;my-index&amp;quot;; subpagepattern=canvas name; defaultregion=side-pre/content/side-post&lt;br /&gt;
** block on all user&#039;s pages: parentcontextid=1 (system context); showinsubcontexts=0; pagetypepattern=&amp;quot;my-index&amp;quot;; subpagepattern=canvas name; defaultregion=side-pre/content/side-post&lt;br /&gt;
* blocks may choose to display different content/different layout depending on what region they are in (e.g. if they are in the &amp;quot;content&amp;quot; region, vs. one of the side regions)&lt;br /&gt;
** The region that a block is in can be obtained by $this-&amp;gt;instance-&amp;gt;region (is this the best way to find this out, or should there be an API call?)&lt;br /&gt;
* blocks can know which user&#039;s My Moodle page is being viewed through $PAGE-&amp;gt;context.&lt;br /&gt;
&lt;br /&gt;
===Subpages===&lt;br /&gt;
* need a new database table: &amp;quot;mdl_my_subpages&amp;quot;(?) that stores&lt;br /&gt;
** user ID of the subpage owner (or 0 for site-wide pages)&lt;br /&gt;
** page name&lt;br /&gt;
** private/public&lt;br /&gt;
** locked? (for site-wide pages only)&lt;br /&gt;
* start with a set of predefined subpages&lt;br /&gt;
** user profile&lt;br /&gt;
** my course list (the current My Moodle contents)&lt;br /&gt;
* NEED: some way of (optionally) doing localization for names of site-wide pages (e.g. profile page)&lt;br /&gt;
&lt;br /&gt;
===Access control===&lt;br /&gt;
* users can access other users&#039; public pages&lt;br /&gt;
* users with &amp;quot;moodle/my:viewprivatesubpages&amp;quot;(?) capability in the user&#039;s context can view the other user&#039;s private pages&lt;br /&gt;
* users can add/edit their own subpages if they have &amp;quot;moodle/my:manageblocks&amp;quot;&lt;br /&gt;
* users can add/edit other users&#039; subpages if they have &amp;quot;moodle/block:edit&amp;quot; ( or a My Moodle-specific capability?) in the user&#039;s context&lt;br /&gt;
* users can add/edit site-wide pages if they have &amp;quot;moodle/my:editsitewidesubpages&amp;quot;(?) in the system context&lt;br /&gt;
&lt;br /&gt;
===Questions===&lt;br /&gt;
* what happens when a user creates a subpage with the same name as a site-wide page?&lt;br /&gt;
** disallow this? (problems with: site-wide page created after a user creates their page)&lt;br /&gt;
** display both tabs separately? (prefix site-wide page names to prevent subpage name collisions?)&lt;br /&gt;
** &amp;quot;merge&amp;quot; contents? (could this present a spoofing vulnerability?)&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* MDL-19124 My Moodle Functional Overhaul&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=122919 New Tracker Item for My Moodle 2.0 Improvements]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=135191 Forum discussion for this page]&lt;br /&gt;
&lt;br /&gt;
[[Category:Developer]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64357</id>
		<title>Development talk:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64357"/>
		<updated>2009-10-13T21:16:20Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Why CONTEXT_MYPAGE? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Why CONTEXT_MYPAGE?==&lt;br /&gt;
&lt;br /&gt;
I don&#039;t see the need for CONTEXT_MYPAGE. I think it is fine if all of My Moodle is in the user context, just like all of the pages of the forum module are in CONTEXT_MODULE.&lt;br /&gt;
&lt;br /&gt;
Of course, different capabilities for whether different bits of My Moodle are visible to a given user makes perfect sense.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:With an extra context level, one could assign different roles to different sub-pages.  If we just used the user context, then the permissions would apply to all of a user&#039;s My Moodle pages.  It could also add the possibility of applying permissions to &amp;quot;&#039;locked&#039; pages that would always be the same layout for all users&amp;quot; (&amp;quot;sticky&amp;quot; pages?), which would not be associated with a specific user context.  (Though I&#039;m not sure if this is how Mike was planning on implementing that feature.)  --[[User:Hubert Chathi|Hubert Chathi]] 20:35, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
::Yes, you could do that, but why would you want to? Give me some use-cases expressed in the user&#039;s vocabulary.--[[User:Tim Hunt|Tim Hunt]] 18:54, 10 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::Assuming we want to do this with block functionality as much as possible (and I assume we do), then you would want to be able to restrict the editing of some subpages to specific roles. For example, the course listing page you will want to always display the course listing information. This would be by pre-configured blocks. You would not want the user to be able to remove this block from that subpage. On the other hand, the home page subpage you would want to give the user free reign over what blocks would be displayed there as well as how they are ordered. I can&#039;t think of any other way to do this except through contexts for the My Moodle pages. --[[User:Mike Churchward|Mike Churchward]] 14:40, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
::::Should we move this discussion to the My Moodle forum? Anyway, I disagree. This feature is called My Moodle. Not &#039;the teacher&#039;s Moodle&#039; - that is the course page - nor &#039;the admin&#039;s Moodle&#039;, that is the site front page. This is a space for user&#039;s to create their personal dashboard. If they don&#039;t want the My courses list, they should be able to delete it. If they suddenly regret deleting it, it should be really easy for them to add that block back. At most, the admin should be able to control the default layout for new users.--[[User:Tim Hunt|Tim Hunt]] 21:05, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::One example is that the admin creates a global &amp;quot;Local News&amp;quot; page, and allows certain people to add content (add RSS feeds or other various blocks), but doesn&#039;t want those users to the global &amp;quot;Site News&amp;quot; page. --[[User:Hubert Chathi|Hubert Chathi]] 14:42, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
::::But surely what you really mean is that the admin will configure a Local News block. And blocks already have a context. In fact, see the OU&#039;s newsfeed block, I think it is in contrib.--[[User:Tim Hunt|Tim Hunt]] 21:05, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
::::: No, I do mean a &amp;quot;Local News&amp;quot; &#039;&#039;page&#039;&#039;, in which certain people may have permission to manage the blocks on that page, and add, remove, or manage content (e.g. a new local news site opened up, so someone can create a new RSS feed block.  Or someone with the right privileges can rearrange the blocks on the page). --[[User:Hubert Chathi|Hubert Chathi]] 21:16, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Can we do it all with blocks?==&lt;br /&gt;
&lt;br /&gt;
I think it would be architecturally very elegant, and maximally flexible, if the whole of My Moodle could be done as blocks. That is, My Moodle would just be a set of empty pages (subpages, or canvases, call them what you will) and all the functionality we might want there would be in the form of blocks.&lt;br /&gt;
&lt;br /&gt;
I cannot immediately see why that would not work, however, I freely admit that I have not thought about this as much as you.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
I think that is what we are saying too. The subpages or canvases are the new elements for My Moodle; everything else is a block. Some can sit in the centre. --[[User:Mike Churchward|Mike Churchward]] 19:42, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Including functionality from other myMoodle modifications==&lt;br /&gt;
&lt;br /&gt;
Ideally, this should include all the additional features that have been added to myMoodle (myCourses sub-page). &lt;br /&gt;
For instance, people have made it possible to show more details about the course, such as the teacher, last access date, etc. &lt;br /&gt;
There are modifications of myMoodle that group courses by category (with different background colours) or sort them by title, or allow user to move them, like topics within a course.&lt;br /&gt;
Maybe it would be worth looking at pagination of courses for users with lots of courses (&amp;gt;50)&lt;br /&gt;
&lt;br /&gt;
I agree. These would be sub-tasks of this entire task to update all of this functionality into new blocks for the My Moodle functions. Then, the effort to make those correct could be added/tracked in those subtasks. --[[User:Mike Churchward|Mike Churchward]] 14:42, 13 October 2009 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64344</id>
		<title>Development talk:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64344"/>
		<updated>2009-10-13T14:42:22Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Why CONTEXT_MYPAGE? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Why CONTEXT_MYPAGE?==&lt;br /&gt;
&lt;br /&gt;
I don&#039;t see the need for CONTEXT_MYPAGE. I think it is fine if all of My Moodle is in the user context, just like all of the pages of the forum module are in CONTEXT_MODULE.&lt;br /&gt;
&lt;br /&gt;
Of course, different capabilities for whether different bits of My Moodle are visible to a given user makes perfect sense.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:With an extra context level, one could assign different roles to different sub-pages.  If we just used the user context, then the permissions would apply to all of a user&#039;s My Moodle pages.  It could also add the possibility of applying permissions to &amp;quot;&#039;locked&#039; pages that would always be the same layout for all users&amp;quot; (&amp;quot;sticky&amp;quot; pages?), which would not be associated with a specific user context.  (Though I&#039;m not sure if this is how Mike was planning on implementing that feature.)  --[[User:Hubert Chathi|Hubert Chathi]] 20:35, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
::Yes, you could do that, but why would you want to? Give me some use-cases expressed in the user&#039;s vocabulary.--[[User:Tim Hunt|Tim Hunt]] 18:54, 10 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::Assuming we want to do this with block functionality as much as possible (and I assume we do), then you would want to be able to restrict the editing of some subpages to specific roles. For example, the course listing page you will want to always display the course listing information. This would be by pre-configured blocks. You would not want the user to be able to remove this block from that subpage. On the other hand, the home page subpage you would want to give the user free reign over what blocks would be displayed there as well as how they are ordered. I can&#039;t think of any other way to do this except through contexts for the My Moodle pages. --[[User:Mike Churchward|Mike Churchward]] 14:40, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::One example is that the admin creates a global &amp;quot;Local News&amp;quot; page, and allows certain people to add content (add RSS feeds or other various blocks), but doesn&#039;t want those users to the global &amp;quot;Site News&amp;quot; page. --[[User:Hubert Chathi|Hubert Chathi]] 14:42, 13 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Can we do it all with blocks?==&lt;br /&gt;
&lt;br /&gt;
I think it would be architecturally very elegant, and maximally flexible, if the whole of My Moodle could be done as blocks. That is, My Moodle would just be a set of empty pages (subpages, or canvases, call them what you will) and all the functionality we might want there would be in the form of blocks.&lt;br /&gt;
&lt;br /&gt;
I cannot immediately see why that would not work, however, I freely admit that I have not thought about this as much as you.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Including functionality from other myMoodle modifications==&lt;br /&gt;
&lt;br /&gt;
Ideally, this should include all the additional features that have been added to myMoodle (myCourses sub-page). &lt;br /&gt;
For instance, people have made it possible to show more details about the course, such as the teacher, last access date, etc. &lt;br /&gt;
There are modifications of myMoodle that group courses by category (with different background colours) or sort them by title, or allow user to move them, like topics within a course.&lt;br /&gt;
Maybe it would be worth looking at pagination of courses for users with lots of courses (&amp;gt;50)&lt;br /&gt;
&lt;br /&gt;
I agree. These would be sub-tasks of this entire task to update all of this functionality into new blocks for the My Moodle functions. Then, the effort to make those correct could be added/tracked in those subtasks. --[[User:Mike Churchward|Mike Churchward]] 14:42, 13 October 2009 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64193</id>
		<title>Development talk:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64193"/>
		<updated>2009-10-09T20:40:34Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Why CONTEXT_MYPAGE? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Why CONTEXT_MYPAGE?==&lt;br /&gt;
&lt;br /&gt;
I don&#039;t see the need for CONTEXT_MYPAGE. I think it is fine if all of My Moodle is in the user context, just like all of the pages of the forum module are in CONTEXT_MODULE.&lt;br /&gt;
&lt;br /&gt;
Of course, different capabilities for whether different bits of My Moodle are visible to a given user makes perfect sense.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
With an extra context level, one could assign different roles to different sub-pages.  If we just used the user context, then the permissions would apply to all of a user&#039;s My Moodle pages.  It could also add the possibility of applying permissions to &amp;quot;&#039;locked&#039; pages that would always be the same layout for all users&amp;quot; (&amp;quot;sticky&amp;quot; pages?), which would not be associated with a specific user context.  (Though I&#039;m not sure if this is how Mike was planning on implementing that feature.)  --[[User:Hubert Chathi|Hubert Chathi]] 20:35, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Can we do it all with blocks?==&lt;br /&gt;
&lt;br /&gt;
I think it would be architecturally very elegant, and maximally flexible, if the whole of My Moodle could be done as blocks. That is, My Moodle would just be a set of empty pages (subpages, or canvases, call them what you will) and all the functionality we might want there would be in the form of blocks.&lt;br /&gt;
&lt;br /&gt;
I cannot immediately see why that would not work, however, I freely admit that I have not thought about this as much as you.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64192</id>
		<title>Development talk:My Moodle 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=Development_talk:My_Moodle_2.0&amp;diff=64192"/>
		<updated>2009-10-09T20:35:28Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* Why CONTEXT_MYPAGE? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Why CONTEXT_MYPAGE?==&lt;br /&gt;
&lt;br /&gt;
I don&#039;t see the need for CONTEXT_MYPAGE. I think it is fine if all of My Moodle is in the user context, just like all of the pages of the forum module are in CONTEXT_MODULE.&lt;br /&gt;
&lt;br /&gt;
Of course, different capabilities for whether different bits of My Moodle are visible to a given user makes perfect sense.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
With an extra context level, one could assign different roles to different sub-pages.  If we just used the user context, then the permissions would apply to all of a user&#039;s My Moodle pages. --[[User:Hubert Chathi|Hubert Chathi]] 20:35, 9 October 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
==Can we do it all with blocks?==&lt;br /&gt;
&lt;br /&gt;
I think it would be architecturally very elegant, and maximally flexible, if the whole of My Moodle could be done as blocks. That is, My Moodle would just be a set of empty pages (subpages, or canvases, call them what you will) and all the functionality we might want there would be in the form of blocks.&lt;br /&gt;
&lt;br /&gt;
I cannot immediately see why that would not work, however, I freely admit that I have not thought about this as much as you.--[[User:Tim Hunt|Tim Hunt]] 18:54, 9 October 2009 (UTC)&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=User:Hubert_Chathi/Custom_Context_Levels&amp;diff=62929</id>
		<title>User:Hubert Chathi/Custom Context Levels</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=User:Hubert_Chathi/Custom_Context_Levels&amp;diff=62929"/>
		<updated>2009-09-11T14:51:40Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: New page: == Custom context levels database == For adding custom context levels, rather than trying to assign level numbers and hoping to not have collisions, I propose that we add a database table ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Custom context levels database ==&lt;br /&gt;
For adding custom context levels, rather than trying to assign level numbers and hoping to not have collisions, I propose that we add a database table to map a context level name to the context level number. If we allow various plugins to define context levels, then we can create a table (which I&#039;ve called mdl_context_levels) that has the following fields:&lt;br /&gt;
* id - the standard record ID&lt;br /&gt;
* name (VARCHAR(255?)) - the name of the context level&lt;br /&gt;
* component (VARCHAR(255?)) - the name and type of the component that defined the context level&lt;br /&gt;
&lt;br /&gt;
The context level number would be id + 1000 (or another sufficiently large number to guarantee that we won&#039;t collide with any Moodle context levels). So if my block &amp;quot;foo&amp;quot; defines the custom context level &amp;quot;bar&amp;quot;, then its context level number would be get_field(&#039;context_levels&#039;, &#039;id&#039;, &#039;name&#039;, &#039;bar&#039;, &#039;component&#039;, &#039;block_foo&#039;)+1000.&lt;br /&gt;
&lt;br /&gt;
Building on the patch that I&#039;ve already uploaded to MDL-20045, I would then add some methods to context_level_base to get the custom context levels (draft -- not finalized):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    private static $customctxlevels;&lt;br /&gt;
&lt;br /&gt;
    private static function load_custom_context_levels() {&lt;br /&gt;
        if (!isset(context_level_base::$customctxlevels)) {&lt;br /&gt;
            $ctxlevel = get_records(&#039;context_levels&#039;);&lt;br /&gt;
            context_level_base::$customctxlevels = array();&lt;br /&gt;
            foreach($ctxlevel as $rec) {&lt;br /&gt;
                context_level_base::$customctxlevels[$rec-&amp;gt;component][$rec-&amp;gt;name] = $rec-&amp;gt;id + 1000;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static function get_custom_context_level($name, $component) {&lt;br /&gt;
        context_level_base::load_custom_context_levels();&lt;br /&gt;
&lt;br /&gt;
        return context_level_base::$customctxlevels[$component][$name];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This provides an API to look up the context level number for a custom context level.&lt;br /&gt;
&lt;br /&gt;
I would also add the following code to the get_all_contexts method:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
            // find all the components that have defined context levels&lt;br /&gt;
            context_level_base::load_custom_context_levels();&lt;br /&gt;
            $components = array();&lt;br /&gt;
            foreach (array_keys(context_level_base::$customctxlevels) as $component) {&lt;br /&gt;
                require (get_component_directory($component).&#039;/db/access.php&#039;);&lt;br /&gt;
                foreach (${$component.&#039;_contextlevels&#039;} as $name=&amp;gt;$object) {&lt;br /&gt;
                    $contextlevel = context_level_base::get_custom_context_level($name, $component);&lt;br /&gt;
                    context_level_base::$allcontextlevels[$contextlevel] = $object;&lt;br /&gt;
                    $object-&amp;gt;level = $contextlevel;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(see below for how {component}/db/access.php is used)&lt;br /&gt;
&lt;br /&gt;
== Adding records to context_levels table ==&lt;br /&gt;
&lt;br /&gt;
In addition to this, we would need code to create the records in the context_levels table.  My prototype code uses a new variable in the {component}/db/access.php file (currently used to define custom capabilities).  e.g., in my blocks/foo/db/access.php file, I would have a variable: &amp;quot;block_foo_contextlevels = array(&#039;bar&#039; =&amp;gt; new context_level_foo_bar());&amp;quot; (where context_level_foo_bar is a subclass of context_level_base).&lt;br /&gt;
&lt;br /&gt;
The code for loading the custom context levels:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Loads the context level definitions for the component (from file). If no&lt;br /&gt;
 * context levels are defined for the component, we simply return an empty&lt;br /&gt;
 * array.&lt;br /&gt;
 * @param string $component - examples: &#039;moodle&#039;, &#039;mod_forum&#039;, &#039;block_quiz_results&#039;&lt;br /&gt;
 * @return array array of contexts levels&lt;br /&gt;
 */&lt;br /&gt;
function load_context_level_def($component=&#039;moodle&#039;) {&lt;br /&gt;
    $defpath = get_component_directory($component).&#039;/db/access.php&#039;;&lt;br /&gt;
&lt;br /&gt;
    $contexts = array();&lt;br /&gt;
    if (file_exists($defpath)) {&lt;br /&gt;
        require($defpath);&lt;br /&gt;
        if (isset(${$component.&#039;_contextlevels&#039;})) {&lt;br /&gt;
            $contexts = array_keys(${$component.&#039;_contextlevels&#039;});&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $contexts;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And I&#039;ve added code to the update_capabilities function:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $filectxlvl = load_context_level_def($component);&lt;br /&gt;
    $strcomp = str_replace(&#039;/&#039;,&#039;_&#039;,$component);&lt;br /&gt;
    $oldctxlvl = get_records(&#039;context_levels&#039;, &#039;component&#039;, $strcomp, &#039;&#039;, &#039;name&#039;);&lt;br /&gt;
    foreach ($filectxlvl as $contextlevel) {&lt;br /&gt;
        if (!isset($oldctxlvl[$contextlevel])) {&lt;br /&gt;
            $level = new object;&lt;br /&gt;
            $level-&amp;gt;name = $contextlevel;&lt;br /&gt;
            $level-&amp;gt;component = $strcomp;&lt;br /&gt;
&lt;br /&gt;
            if (!insert_record(&#039;context_levels&#039;, $level, false, &#039;id&#039;)) {&lt;br /&gt;
                return false;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // FIXME: remove old context levels&lt;br /&gt;
    // what needs to be cleaned up?&lt;br /&gt;
    // - contexts (and kill all sub-contexts?)&lt;br /&gt;
    // - role assignments&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=curriculum_mapping&amp;diff=50663</id>
		<title>curriculum mapping</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=curriculum_mapping&amp;diff=50663"/>
		<updated>2009-02-10T19:04:50Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: /* What is curriculum mapping? */ Add more details about what it is&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is curriculum mapping? ==&lt;br /&gt;
&amp;quot;Curriculum mapping&amp;quot; is a tool that many schools are using to record class curriculum.  It is (real-time) record of what is being taught and how it is being taught. Curriculum maps can be used to, for example, figure out if students were introduced to material that they should have been in previous terms, or for parents to see what is happening in the classroom.&lt;br /&gt;
&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Curriculum_mapping Wikipedia article] &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This page, at this time, is just a &amp;quot;stub&amp;quot; that others can add to as we brainstorm what we would like Moodle to do.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== A Moodle Curriculum Mapping component? ==&lt;br /&gt;
There is currently no component for Moodle designed for curriculum mapping. This page is dedicated towards spawning the development of such a component.&lt;br /&gt;
&lt;br /&gt;
== Basic roles of a Moodle curriculum mapping component ==&lt;br /&gt;
&#039;&#039;&#039;Note: Not all teachers who are mapping will be using Moodle for their courses.&#039;&#039;&#039; Also, it is important that the curriculum mapping module be accessible to teachers and administrators other than the teacher whose course is being mapped.&lt;br /&gt;
&lt;br /&gt;
=== Components for teacher input ===&lt;br /&gt;
* Allow teachers to enter brief descriptions of each unit of their class.&lt;br /&gt;
* A field for keywords (probably linked from a set of standard keywords).&lt;br /&gt;
* The ability to include the approximate time duration of the unit.&lt;br /&gt;
* The ability to check off which of the required &amp;quot;state standards&amp;quot; (a list provided by the school/government of the curriculum to be covered by the course).&lt;br /&gt;
* The ability to enter the grade level of the class, and multiple grade levels for some classes.&lt;br /&gt;
&lt;br /&gt;
=== Search components ===&lt;br /&gt;
* The ability for an administrator or parent to see &amp;quot;what should Janie be learning now in her [input subject] class?&lt;br /&gt;
* The ability for a teacher to ask &amp;quot;what classes besides mine are covering [input keyword/topic]?&lt;br /&gt;
&lt;br /&gt;
=== Components for reports ===&lt;br /&gt;
* The ability to generate a calendared report of topics covered. &lt;br /&gt;
&lt;br /&gt;
=== Back-end requirements ===&lt;br /&gt;
* The ability to import &amp;quot;state standards&amp;quot; (a list provided by the school/government of the curriculum to be covered by the course).&lt;br /&gt;
&lt;br /&gt;
== Commercial Curriculum Mapping services == &lt;br /&gt;
* [http://www.rubicon.com/AtlasCurriculumMapping.html Atlas Curriculum Mapping]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/31/en/index.php?title=MNet_FAQ&amp;diff=48111</id>
		<title>MNet FAQ</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/31/en/index.php?title=MNet_FAQ&amp;diff=48111"/>
		<updated>2008-12-12T14:18:59Z</updated>

		<summary type="html">&lt;p&gt;Hchathi: added note about not working on lighttpd&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}==What is MNET?==&lt;br /&gt;
&lt;br /&gt;
MNET is the mechanism in Moodle for connecting to other Moodle (or Mahara) sites. It&#039;s short for &amp;quot;Moodle Network&amp;quot;. See [[Moodle Network]] for more information.&lt;br /&gt;
&lt;br /&gt;
==It doesn&#039;t work. What do I do now?==&lt;br /&gt;
&lt;br /&gt;
Always make sure you have the latest version possible of Moodle. There have been a lot of fixes. Then make sure that you have debugging turned on (Site Administration &amp;gt; Server &amp;gt; Debugging). This will greatly increase the chance of the underlying problem being reported.&lt;br /&gt;
&lt;br /&gt;
Note that MNET currently does not currently work on lighttpd.  (MDL-14638)  This should be fixed in lighttpd 1.5 when it is released.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/view.php?id=6976 Moodle Network forum]&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/discuss.php?d=105301 Overview of public key] forum discussion&lt;br /&gt;
&lt;br /&gt;
[[Category:MNET]]&lt;br /&gt;
[[Category:FAQ]]&lt;/div&gt;</summary>
		<author><name>Hchathi</name></author>
	</entry>
</feed>