<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iarenaza</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iarenaza"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Iarenaza"/>
	<updated>2026-04-16T06:19:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_2.0_release_notes&amp;diff=25916</id>
		<title>Moodle 2.0 release notes</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_2.0_release_notes&amp;diff=25916"/>
		<updated>2010-11-25T14:00:26Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Fix credits for Iñaki Arenaza (or my employer will complain ;-)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Release date: &#039;&#039;&#039;24th November, 2010&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Moodle 2.0 contains a lot of large new features, some completely rewritten features, and hundreds of bug fixes.  For full details (more than you probably want!), see [http://tracker.moodle.org/browse/MDL/fixforversion/10122 the full list of fixed issues in 2.0].&lt;br /&gt;
&lt;br /&gt;
===Major new features===&lt;br /&gt;
&lt;br /&gt;
====[[Community hub|Community hubs]]====&lt;br /&gt;
&lt;br /&gt;
* Anybody can set up a Community hub, which is a directory of courses for public use or for private communities.  The code is implemented as separate GPL plugin for Moodle.&lt;br /&gt;
* Sites can register to any Community hub (instead of just moodle.org)&lt;br /&gt;
* Teachers on registered sites can publish their full courses to Community hubs, for download&lt;br /&gt;
* Teachers on registered sites can also advertise their courses on Community hubs, for people to join&lt;br /&gt;
* Teachers on any site can search all public Community hubs and download courses as templates for their own courses&lt;br /&gt;
* Users on any Moodle site can also search Community hubs for courses (and communities of practice) to participate in.  Initially we are encouraging &#039;&#039;&#039;&#039;communities of teaching practice&#039;&#039;&#039;&#039; but any sort of course can be listed.&lt;br /&gt;
&lt;br /&gt;
====[[Repositories|Repository support]]====&lt;br /&gt;
&lt;br /&gt;
* Moodle now supports integration with external repositories of content, making it really simple to bring documents and media into Moodle via an AJAX interface that looks like a standard &#039;&#039;&#039;Open&#039;&#039;&#039; dialogue in desktop applications.&lt;br /&gt;
* Initial plugins in 2.0 include: Alfresco, Amazon S3, Box.net, File system on Server, Flickr, Google Docs, Mahara, MERLOT, Picasa, Recent Files, Remote Moodle sites, WebDAV servers, Wikimedia, Youtube.  These are simple to develop, so many more are expected.&lt;br /&gt;
* You can also import files from your desktop or by specifying a URL.&lt;br /&gt;
&lt;br /&gt;
====[[Portfolios|Portfolio support]]====&lt;br /&gt;
&lt;br /&gt;
* Modules can now export their data to external systems, particularly useful for portfolios where snapshots of forums, assignments and other things in Moodle are useful to record in a journal or a portfolio of evidence&lt;br /&gt;
* Different formats are supported (currently LEAP2A, HTML, Images and Text, but others like PDF can be added)&lt;br /&gt;
* Initial plugins in 2.0 include: Box.net, Flickr, Google Docs, &#039;&#039;&#039;Mahara&#039;&#039;&#039; and Picasa.&lt;br /&gt;
&lt;br /&gt;
====[[Completion]]====&lt;br /&gt;
&lt;br /&gt;
* Teachers can now specify conditions that define when any &#039;&#039;&#039;activity&#039;&#039;&#039; is seen as completed by a student.  For example, when a certain number of posts have been made, or a grade has been reached, or a choice has been made.  &lt;br /&gt;
* Teachers can now specify conditions that define with any &#039;&#039;&#039;course&#039;&#039;&#039; is seen as completed by a student.  Conditions include activity completion, but could also be by grade, date or a number of other criteria.&lt;br /&gt;
* Teachers and students can see reports that show the progress of any user within a course, or through a series of courses.&lt;br /&gt;
&lt;br /&gt;
====[[Conditional activities]]====&lt;br /&gt;
&lt;br /&gt;
* Access to activities can be restricted based on certain criteria, such as dates, grade obtained, or the completion of another activity.  &lt;br /&gt;
* These can be chained together to enable progressive disclosure of the course content, if that is desired. &lt;br /&gt;
&lt;br /&gt;
====[[Cohorts]]====&lt;br /&gt;
* Also known as &amp;quot;Site-wide groups&amp;quot;, these are site-wide collections of users that can be enrolled into courses in one action, either manually or synchronised automatically&lt;br /&gt;
&lt;br /&gt;
====[[Web Services|Web services support]]====&lt;br /&gt;
* Support for standards-based web services across the entire Moodle code base, allowing the admin to expose particular functions of Moodle for use by:&lt;br /&gt;
** Administrative systems such as HR or SIS applications&lt;br /&gt;
** Mobile clients&lt;br /&gt;
* Framework contains a very high-level of security with a detailed token system and complete control over the range of functions exposed&lt;br /&gt;
* All defined functions are automatically available via:&lt;br /&gt;
** XML-RPC&lt;br /&gt;
** AMF (Flash)&lt;br /&gt;
** REST&lt;br /&gt;
** SOAP (PHP)&lt;br /&gt;
&lt;br /&gt;
====New blocks====&lt;br /&gt;
* [[Comments block]] - like a shoutbox, allows comments to be added to any page. Great for student feedback.&lt;br /&gt;
* [[My private files block]] - allows easy access to one&#039;s private file repository in Moodle (with quota support)&lt;br /&gt;
* [[Community block]] - keeps track of external courses one is interested in &lt;br /&gt;
* [[Course completion status block]] - reports on the completion status of your courses&lt;br /&gt;
&lt;br /&gt;
====[[Plagiarism Prevention|Plagiarism prevention]]====&lt;br /&gt;
&lt;br /&gt;
* Moodle supports integration with plagiarism prevention tools such as Turnitin&lt;br /&gt;
&lt;br /&gt;
===Major improvements to existing core features===&lt;br /&gt;
&lt;br /&gt;
====[[Backup 2.0|Backup and restore]]====&lt;br /&gt;
&lt;br /&gt;
* Completely rewritten Backup/Restore framework, no longer bound by memory (can work with &#039;&#039;&#039;any size course&#039;&#039;&#039;).&lt;br /&gt;
* Completely new backup format.&lt;br /&gt;
* Improved interface.&lt;br /&gt;
* Backup can be made of whole courses, but also specific sections or activities.&lt;br /&gt;
&lt;br /&gt;
====[[Blocks 2.0|Blocks]]====&lt;br /&gt;
* Blocks are now consistently implemented on every page in Moodle&lt;br /&gt;
* No longer any limit to the block regions (in addition to left and right, put them at the top, center or bottom of pages)&lt;br /&gt;
* Any block can be made sticky (appears in all the contexts below, eg throughout a course).&lt;br /&gt;
* Blocks can be &amp;quot;docked&amp;quot; on the side of the screen (if the theme supports it)&lt;br /&gt;
&lt;br /&gt;
====[[Blogs 2.0|Blogs]]====&lt;br /&gt;
* Support for comments on each blog entry&lt;br /&gt;
* Removal of group-level and course-level blogs (these are converted into forums on upgrade)&lt;br /&gt;
* Support for external blog feeds (synchronised to Moodle blog)&lt;br /&gt;
&lt;br /&gt;
====[[Comments 2.0|Comments]]====&lt;br /&gt;
* User comments (Glossaries, Databases, Blogs, etc) are now all consistently handled  and displayed throughout Moodle, using AJAX if available&lt;br /&gt;
&lt;br /&gt;
====[[Enrolments 2.0|Enrolment plugins]]====&lt;br /&gt;
* Major improvements in the handling of guests and guest accounts &lt;br /&gt;
* Support for multiple forms of enrolment at the same time &lt;br /&gt;
* More detailed control over enrolment in courses &lt;br /&gt;
&lt;br /&gt;
====[[File handling 2.0|File handling]]====&lt;br /&gt;
&lt;br /&gt;
* Full support for Unicode file names on all operating systems.&lt;br /&gt;
* Metadata about each file (author, date, license, etc) and what the file is used for are stored in the database.&lt;br /&gt;
* Duplicate files (for example, a large video file use in two different courses) are only stored once, saving disk space.&lt;br /&gt;
* Files are no longer just &amp;quot;uploaded to the course&amp;quot;.  Files are connected to the particular bit of Moodle content that uses them. (For example, a file may belong to a file resource, a forum post or a wiki page). Access to these files is then controlled by the same rules as as that bit of Moodle, increasing security.&lt;br /&gt;
&lt;br /&gt;
====[[Filters 2.0]]====&lt;br /&gt;
&lt;br /&gt;
* In the past, you had to use the same filters everywhere in your Moodle site, and this could only be changed by admins.&lt;br /&gt;
* Now, you can have different filters in different courses, activities or categories.&lt;br /&gt;
* For example, you could turn on the LaTeX filter just for courses in the Maths and Physics categories.&lt;br /&gt;
* Or you could turn off glossary linking in the end of course exam.&lt;br /&gt;
&lt;br /&gt;
====[[HTML editor 2.0|HTML editor]]====&lt;br /&gt;
* New editor based on TinyMCE&lt;br /&gt;
* Works on more browsers&lt;br /&gt;
* Resizable editing area&lt;br /&gt;
* Cleaner XHTML output &lt;br /&gt;
* Full integration with configured external repositories to import and embed media into text&lt;br /&gt;
&lt;br /&gt;
====[[Messaging 2.0|Messaging]]====&lt;br /&gt;
* All email sent by Moodle is now treated as a message&lt;br /&gt;
* A message overview panel allows users to control how messages are sent to them&lt;br /&gt;
* Initial message output plugins in Moodle 2.0 include: Email, Jabber and Popups&lt;br /&gt;
&lt;br /&gt;
====[[My Moodle 2.0|My Moodle page]]====&lt;br /&gt;
* More customisable My Moodle page with new blocks for showing relevant information &lt;br /&gt;
* Admin can design (and optionally force) site-wide layouts for My Moodle&lt;br /&gt;
* My Moodle page given more prominence as the main &amp;quot;home page&amp;quot; for users&lt;br /&gt;
&lt;br /&gt;
====[[Navigation 2.0|Navigation]]====&lt;br /&gt;
* Standard &amp;quot;Navigation&amp;quot; block on every page showing contextual links, while allowing you to jump elsewhere quickly&lt;br /&gt;
* Standard &amp;quot;Settings&amp;quot; blocks on every page shows contextual settings as well as settings for anything else you have permissions for&lt;br /&gt;
&lt;br /&gt;
====[[Ratings 2.0|Ratings]]====&lt;br /&gt;
* User ratings (Glossaries, Databases, Forums, etc) are now all consistently handled and displayed throughout Moodle, using AJAX if available&lt;br /&gt;
* Aggregation of using ratings into activity grades is now standardised in all activities&lt;br /&gt;
&lt;br /&gt;
====[[Roles 2.0|Roles and permissions]]====&lt;br /&gt;
* Improved and simplified AJAX interfaces for defining and assigning roles&lt;br /&gt;
* Improved and simplified interfaces for tweaking permissions in any given context &lt;br /&gt;
* New &amp;quot;Archetypes&amp;quot; concept replacing the &amp;quot;Legacy roles&amp;quot; concept.&lt;br /&gt;
* New archetype &amp;quot;manager&amp;quot; to define the role of most people with system-wide editing rights, separate from &amp;quot;admin&amp;quot; role.&lt;br /&gt;
&lt;br /&gt;
====[[RSS feeds 2.0|RSS feeds]]====&lt;br /&gt;
* All RSS feeds are now secured using a random per-user token in the URL&lt;br /&gt;
* Tokens can be updated by the user at any time (if they suspect a feed URL has been compromised)&lt;br /&gt;
* RSS feeds are now more accurate (eg they support forums with separate groups), and are generated efficiently whenever required&lt;br /&gt;
&lt;br /&gt;
====[[Development:Themes 2.0|Themes]]====&lt;br /&gt;
* Many new themes in the core distribution - see [[Theme credits]] for a list&lt;br /&gt;
* All HTML and JS ouput is now far more efficient (server-side caching) and consistent (tableless layout, new CSS, YUI Framework)&lt;br /&gt;
* Themes can change the HTML of the page if they wish&lt;br /&gt;
* Core support for custom menus in all themes (for example at the top of the page)&lt;br /&gt;
&lt;br /&gt;
====[[Translation 2.0|Translation system]]====&lt;br /&gt;
* [http://lang.moodle.org/ New web portal] to make it easer for groups to collaborate on translating Moodle, and to keep their translations up-to-date.&lt;br /&gt;
* More efficient [[Development:Languages/AMOS|storage format for language strings]] should slightly improve performance.&lt;br /&gt;
&lt;br /&gt;
====User profile pages====&lt;br /&gt;
* Site-wide user profile page can be customised by users with blocks, news, feeds and so on&lt;br /&gt;
* Course-specific user profile pages show course blocks and standard profile information, plus information for teachers of that course&lt;br /&gt;
&lt;br /&gt;
===Major improvements to activity modules===&lt;br /&gt;
&lt;br /&gt;
====Lesson====&lt;br /&gt;
* Refactored internal code &lt;br /&gt;
* Forms are now standard Moodle forms&lt;br /&gt;
&lt;br /&gt;
====Quiz module and question bank====&lt;br /&gt;
&lt;br /&gt;
* [[Development:quiz_navigation|Quiz navigation improvements for students]]&lt;br /&gt;
* [[Development:Flagging_questions_during_a_quiz_attempt|Flagging questions during a quiz attempt]] &lt;br /&gt;
* [[Development:Quiz_report_enhancements|Quiz report enhancements]] - Major improvements to the quiz reports, especially regrading and item analysis&lt;br /&gt;
* [[Development:Quiz_report_statistics|Quiz report statistics]] - A brief guide&lt;br /&gt;
* [[Development:Quiz_UI_redesign|Quiz editing interface improvements]]&lt;br /&gt;
* Different settings (open/close date, number of attempts, password, time limit) for each group or student (MDL-16478)&lt;br /&gt;
* [[Development:Administration page for question types|Administration page for question types]]&lt;br /&gt;
* [[Development:Moodle 2.0 question bank improvements|Question tagging and improved searching in the question bank]]&lt;br /&gt;
* MDL-8648 Essay questions can now be randomised by random questions&lt;br /&gt;
&lt;br /&gt;
====Resource====&lt;br /&gt;
* All the resource types have been refactored into real modules, and cleaned up&lt;br /&gt;
** File - for displaying a file, possibly with supporting files (like a HTML mini-site)&lt;br /&gt;
** Folder - for displaying a collection of documents &lt;br /&gt;
** URL - for displaying a page with a given URL&lt;br /&gt;
** Page - for a single page, edited online using the HTML editor&lt;br /&gt;
** IMS - for showing a regular IMS content package&lt;br /&gt;
* Better XHTML-compliant support for frames, iframes and embedding in all these modules&lt;br /&gt;
&lt;br /&gt;
====SCORM====&lt;br /&gt;
&lt;br /&gt;
* New [[SCORM module]] settings - display attempt status, display course structure, force completed, force new attempt, lock after final attempt - allowing the behaviour dictated to the SCORM object by the authoring package to be changed MDL-11501 &lt;br /&gt;
* New reporting interface including sortable/collapsible table with group select box and ability to download in Excel, ODS and text format MDL-21555&lt;br /&gt;
* New SCORM player UI with better navigation, improved performance and better handling of stage size MDL-22951&lt;br /&gt;
&lt;br /&gt;
====[[Wiki module 2.0|Wiki]]====&lt;br /&gt;
* Completely re-written from scratch, based on NWIki from UPC&lt;br /&gt;
* Support for Mediawiki-style syntax, as well as Creole &lt;br /&gt;
* Interface improvements &lt;br /&gt;
&lt;br /&gt;
====[[Workshop module 2.0|Workshop]]====&lt;br /&gt;
&lt;br /&gt;
* Completely rewritten from scratch &lt;br /&gt;
* Vastly improved interface for managing stages and users&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;==System requirements==&lt;br /&gt;
&lt;br /&gt;
Since Moodle 2.0 is such a major release, we are allowing ourselves some increases in the requirements.&lt;br /&gt;
&lt;br /&gt;
* PHP must be 5.2.8 or later (it was released 08-Dec-2008)&lt;br /&gt;
* Databases should be one of the following:&lt;br /&gt;
** MySQL 5.0.25 or later  (InnoDB storage engine highly recommended)&lt;br /&gt;
** PostgreSQL 8.3 or later&lt;br /&gt;
** Oracle 10.2 or later&lt;br /&gt;
** MS SQL 2005 or later&lt;br /&gt;
* Any standards-supporting browser from the past few years, for example:&lt;br /&gt;
** Firefox 3 or later &lt;br /&gt;
** Safari 3 or later &lt;br /&gt;
** Google Chrome 4 or later&lt;br /&gt;
** Opera 9 or later&lt;br /&gt;
** MS Internet Explorer 7 or later (Even [http://googleenterprise.blogspot.com/2010/01/modern-browsers-for-modern-applications.html Google don&#039;t support IE6 any more])&lt;br /&gt;
** etc&lt;br /&gt;
&lt;br /&gt;
==Upgrading==&lt;br /&gt;
&lt;br /&gt;
When upgrading to Moodle 2.0, you must have Moodle 1.9 or later.  if you are using an earlier version of Moodle (eg 1.8.x) then you need to upgrade to Moodle 1.9.x first. We advise that you test the upgrade first on a COPY of your production site, to make sure it works as you expect.&lt;br /&gt;
&lt;br /&gt;
For further information, see [[Upgrading to Moodle 2.0]].&lt;br /&gt;
&lt;br /&gt;
==For developers: API changes==&lt;br /&gt;
&lt;br /&gt;
See [[Development:Migrating contrib code to 2.0]]&lt;br /&gt;
&lt;br /&gt;
* [[Development:Plugin system changes in Moodle 2.0]] - all the different types of plugin are now handles more consistently when it comes to installation and upgrading, capabilities, events, and so on.&lt;br /&gt;
* [[Development:DB_layer_2.0_migration_docs|Database layer changes]] - you will need to update your code.&lt;br /&gt;
* [[Development:Using_the_file_API|File handling changes]] - you will need to update your code.&lt;br /&gt;
* [[Development:Migrating your code code to the 2.0 rendering API|Rendering layer changes]] - should be mostly backwards compatible, but you are advised to upgrade your code.&lt;br /&gt;
* Require capability used to do an automatic require_login. It no longer does so. All pages must explicitly call require_login if they need it. MDL-19882&lt;br /&gt;
* [[Development:Moodle_2.0_question_type_API_changes|Changes to the question type API]]&lt;br /&gt;
* MNet has been refactored and tidied up - related third party code needs to be checked&lt;br /&gt;
* Changes and improvements to the [[Development:Local_customisation|Local customisation system]].&lt;br /&gt;
* Javascript &lt;br /&gt;
* YUI&lt;br /&gt;
* custom profile fields values are loaded into $USER-&amp;gt;profile array instead of directly into $USER object&lt;br /&gt;
&lt;br /&gt;
==Credits==&lt;br /&gt;
&lt;br /&gt;
These people made check-ins to Moodle 2.0 code.  Thanks to all of them, of course.  Some of these people represent a team of people who actually worked on the code.&lt;br /&gt;
&lt;br /&gt;
* Robert Allerstorfer (anet.at)&lt;br /&gt;
* Aaron Barnes, Peter Bulmer, Matt Clarkson, Jonathan Harker, Piers Harding, Luke Hudson, Martin Langhoff, Dan Marsden, Francois Marier, Donal McMullan, Jonathan Newman (catalyst.net.nz)&lt;br /&gt;
* Howard Miller (e-learndesign.co.uk)&lt;br /&gt;
* Iñaki Arenaza (mondragon.edu)&lt;br /&gt;
* Andreas Grabs (grabs-edv.de)&lt;br /&gt;
* Jamie Pratt (jamiep.org)&lt;br /&gt;
* Anthony Borrow (jesuits.net)&lt;br /&gt;
* Gordon Bateson (kanazawa-gu.ac.jp)&lt;br /&gt;
* Samuli Karevaara (lamk.fi)&lt;br /&gt;
* Penny Leach (liip.ch)&lt;br /&gt;
* Dan Poltawski (luns.net.uk)&lt;br /&gt;
* Matt Oquist (majen.net)&lt;br /&gt;
* Roberto Pinna (mfn.unipmn.it)&lt;br /&gt;
* Michael Ketcham (microsoft.com)&lt;br /&gt;
* Mitsuhiro Yoshida (mitstek.com)&lt;br /&gt;
* Aparup Banerjee, Dongsheng Cai, Nicolas Connault, Andrew Davis, Martin Dougiamas, Helen Foster, Sam Hemelryk, Eloy Lafuente, Jerome Mouneyrac, David Mudrak, Mathieu Petit-Clair, Petr Skoda, Rossiani Wijaya, Yu Zhang (moodle.com)&lt;br /&gt;
* Mark Nielsen (moodlerooms.com)&lt;br /&gt;
* Andrea Bicciolo (mtouch.it)&lt;br /&gt;
* John Beedell, Nicholas Freear, Jenny Gray, Tim Hunt, Sam Marshall, Gareth Morgan, Derek Woolhead (open.ac.uk)&lt;br /&gt;
* Ashley Holman (netspot.com.au)&lt;br /&gt;
* Patrick Malley (newschoollearning.com)&lt;br /&gt;
* Eric Merrill (oakland.edu)&lt;br /&gt;
* Mike Churchward (oktech.ca)&lt;br /&gt;
* Shane Elliott (pukunui.com)&lt;br /&gt;
* Shamim Rezaie (rezaie.info)&lt;br /&gt;
* Joseph Rezeau (rezeau.org)&lt;br /&gt;
* Lukas Haemmerle (switch.ch)&lt;br /&gt;
* Urs Hunkler (unodo.de)&lt;br /&gt;
* Jordi Piguillem (upc.edu.es)&lt;br /&gt;
* Pierre Pichet (uqam.ca)&lt;br /&gt;
* Gustav Delius (york.ac.uk)&lt;br /&gt;
* Ethem Evlice, Valery Fremaux, Dariem Garces, Wen Hao Chuang, Luis Rodrigues, Olli Savolainen, John Stabinger&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Moodle 2.0 Preview 1 release notes]] - May 4, 2010&lt;br /&gt;
* [[Moodle 2.0 Preview 2 release notes]] - May 17, 2010&lt;br /&gt;
* [[Moodle 2.0 Preview 3 release notes]] - May 31, 2010&lt;br /&gt;
* [[Moodle 2.0 Preview 4 release notes]] - June 30, 2010&lt;br /&gt;
* [[Moodle 2.0 Release Candidate 1 release notes]] - September 21, 2010&lt;br /&gt;
&lt;br /&gt;
[[Category:Release notes]]&lt;br /&gt;
[[Category:Moodle 2.0]]&lt;br /&gt;
&lt;br /&gt;
[[fr:Notes de mise à jour de Moodle 2.0]]&lt;br /&gt;
[[es:Notas de Moodle 2.0]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=New_enrolments_in_2.0&amp;diff=17866</id>
		<title>New enrolments in 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=New_enrolments_in_2.0&amp;diff=17866"/>
		<updated>2010-08-08T03:14:43Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: LDAP enrolment implemented&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = New enrolments in 2.0&lt;br /&gt;
|state = Work in progress&lt;br /&gt;
|tracker = MDL-21782&lt;br /&gt;
|discussion = n/a&lt;br /&gt;
|assignee = [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
=Overview=&lt;br /&gt;
The major difference from 1.6-1.9 enrolments is that the course enrolment information is stored again in a separate database table &#039;&#039;user_enrolments&#039;&#039;. The enrolment related information was move from &#039;&#039;course&#039;&#039; table to new &#039;&#039;enrol&#039;&#039; table which holds plugin instances. The old enrolment plugins need to be completely rewritten. Course category enrolments via role assignments is not possible any more, existing category enrolments are migrated to new cohorts and cohort enrolment plugin.&lt;br /&gt;
&lt;br /&gt;
The benefits are:&lt;br /&gt;
* we can use SQL to find enrolled users in any course extremely quickly (much better performance)&lt;br /&gt;
* multiple enrolment plugins per course are full supported (includes more instances of the same type)&lt;br /&gt;
* new enrolment overview interface&lt;br /&gt;
* user enrolments may be suspended and reactivated&lt;br /&gt;
* plugin may prevent users to change/break  enrolment synchronised with external systems&lt;br /&gt;
* finer access control, more flexible/configurable course settings UI&lt;br /&gt;
* no hardcoded enrolment behaviour - it is possible to completely replace guest access, self enrolments, etc. with custom plugins&lt;br /&gt;
&lt;br /&gt;
=Database structure changes=&lt;br /&gt;
&lt;br /&gt;
==New user_enrolments table==&lt;br /&gt;
New table which stores users participating in courses (aka enroled users). It can be used directly in SQL joins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Default&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| auto-incrementing&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| status&lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| 0 means active enrolment, 1 means suspended, anything else means inactive (user can not access course) and is defined by plugin&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;enrolid&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| foreign key, references enrol.id&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;userid&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| foreign key, references user.id&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;timestart&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| time stamp, start of active participation period&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;timeend&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| time stamp, end of active participation period&lt;br /&gt;
|-&lt;br /&gt;
| modifierid&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| last user who modified enrolment, references user.id&lt;br /&gt;
|-&lt;br /&gt;
| timemodified&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| timestamp, last modification&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==New enrol table==&lt;br /&gt;
Stores information about enrolment plugins used in course, includes plugin configuration data and instance status. The optional fields have plugin specific meanings, plugins may define other tables related via the enrol.id if necessary.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
! Field&lt;br /&gt;
! Type&lt;br /&gt;
! Default&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| auto-incrementing&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;enrol&#039;&#039;&#039; &lt;br /&gt;
| char(20)&lt;br /&gt;
| &lt;br /&gt;
| enrolment plugin name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;status&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| 0 means active plugin, anything else means inactive (user can not access course) and is defined by plugin&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;courseid&#039;&#039;&#039; &lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| foreign key, references course.id&lt;br /&gt;
|-&lt;br /&gt;
| sortorder&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| order of instances in course&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| char(255)&lt;br /&gt;
| &lt;br /&gt;
| optional plugin instance name, useful when multiple instances of the same plugin used in course&lt;br /&gt;
|-&lt;br /&gt;
| enrolperiod&lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| optional default enrolment period, in seconds&lt;br /&gt;
|-&lt;br /&gt;
| enrolstartdate&lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| timestamp, optional default enrolment start date&lt;br /&gt;
|-&lt;br /&gt;
| enrolenddate&lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| timestamp, optional default enrolment end date&lt;br /&gt;
|-&lt;br /&gt;
| expirynotify&lt;br /&gt;
| int(1)&lt;br /&gt;
| 0&lt;br /&gt;
| optional flag&lt;br /&gt;
|-&lt;br /&gt;
| expirythreshold&lt;br /&gt;
| int(10)&lt;br /&gt;
| 0&lt;br /&gt;
| timestamp, optional &lt;br /&gt;
|-&lt;br /&gt;
| notifyall&lt;br /&gt;
| int(1)&lt;br /&gt;
| 0&lt;br /&gt;
| optional flag&lt;br /&gt;
|-&lt;br /&gt;
| password&lt;br /&gt;
| char(255)&lt;br /&gt;
| &lt;br /&gt;
| optional enrolment password&lt;br /&gt;
|-&lt;br /&gt;
| cost&lt;br /&gt;
| char(20)&lt;br /&gt;
| &lt;br /&gt;
| optional cost field&lt;br /&gt;
|-&lt;br /&gt;
| currency&lt;br /&gt;
| char(3)&lt;br /&gt;
| &lt;br /&gt;
| optional currency field&lt;br /&gt;
|-&lt;br /&gt;
| roleid&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customint1&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customint2&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customint3&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customint4&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customchar1&lt;br /&gt;
| char(255)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customchar2&lt;br /&gt;
| char(255)&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customdec1&lt;br /&gt;
| decimal&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customdec2&lt;br /&gt;
| decimal&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customtext1&lt;br /&gt;
| text&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| customtext2&lt;br /&gt;
| text&lt;br /&gt;
| &lt;br /&gt;
| general optional field&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| timestamp, date when instance created&lt;br /&gt;
|-&lt;br /&gt;
| timemodified&lt;br /&gt;
| int(10)&lt;br /&gt;
| &lt;br /&gt;
| timestamp, date when instance last modified&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Simplified role_assignments table==&lt;br /&gt;
No role assignment duration, it could never work for future dates and was not implemented for past dates anyway. The enrol field was renamed to component in order to properly support protected role assignments in auth plugins. The component+itemid is used for protection of each separate enrol instance or auth plugins.&lt;br /&gt;
&lt;br /&gt;
==Simplified course table==&lt;br /&gt;
All enrol related info moved into enrol tables. All code that was looking for enrol related info in course table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
=Enrolment plugins=&lt;br /&gt;
Enrolment framework is fully pluggable, there should not be any hardcoded dependencies in code any more. Technically you may delete all enrol plugins and only new custom plugins. Plugins may integrate at:&lt;br /&gt;
* new admin settings pages&lt;br /&gt;
* login process hook - user enrol sync&lt;br /&gt;
* two require_login() hooks&lt;br /&gt;
* enrol page hoop&lt;br /&gt;
* unenrol support hook&lt;br /&gt;
* course edit page - plugin settings for each course&lt;br /&gt;
* course enrolment methods list - add, remove, hide enrol instances&lt;br /&gt;
* course admin navigation hook&lt;br /&gt;
* management of enrolled users&lt;br /&gt;
* cron script&lt;br /&gt;
* etc.&lt;br /&gt;
&lt;br /&gt;
==Manual enrolments==&lt;br /&gt;
Implemented in /enrol/manual/*, true manual enrolments.&lt;br /&gt;
&lt;br /&gt;
==Temporary guest access==&lt;br /&gt;
Implemented in /enrol/guest/*. This plugin does not use user_enrolments table. The course access is granted inside require_login() call together with a temporary guest role. Access key is optional.&lt;br /&gt;
&lt;br /&gt;
==Self enrolment==&lt;br /&gt;
Implemented in /enrol/self/*.  Users decide when to enrol.  Enrolment key is optional, it can use group enrolment keys too.&lt;br /&gt;
&lt;br /&gt;
==Cohort enrolment==&lt;br /&gt;
Implemented in /enrol/cohort/*. Synchronises cohort users with course enrolment, optionally assigns group too. The sync is implemented through event listeners.&lt;br /&gt;
&lt;br /&gt;
==Course meta links==&lt;br /&gt;
Implemented in /enrol/meta/*. Replaces old metacourses. The difference is that every course may be child and parent course at the same time. The sync is implemented through event listeners. It is possible to mix meta enrolments with normal enrolments.&lt;br /&gt;
&lt;br /&gt;
==External database==&lt;br /&gt;
Implemented in /enrol/database/*. Separate course creation and user synchronisation, more sync options implemented.&lt;br /&gt;
&lt;br /&gt;
==LDAP==&lt;br /&gt;
Implemented in /enrol/ldap/*. Includes course creation and user synchronisation, more sync options implemented (e.g., nested groups on Active Directory).&lt;br /&gt;
&lt;br /&gt;
==Authorize==&lt;br /&gt;
TODO - luckily we do not need any more hardcoded hooks all over the place ;-)&lt;br /&gt;
&lt;br /&gt;
==Flat file==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==imsenterprise==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PayPal==&lt;br /&gt;
TODO - it will be finally possible to set up multiple instances per course, each with different cost&amp;amp;role&lt;br /&gt;
&lt;br /&gt;
==MNET==&lt;br /&gt;
TODO - this needs more internal changes in mnet stuff ...&lt;br /&gt;
&lt;br /&gt;
=Upgrade=&lt;br /&gt;
The data from role assignments table and course table is used to create all necessary entries in enrol and user_enrolments tables. External sync plugins may need to do a full resync. No data is lost during the upgrade, the data from course table is automatically migrated into enrol table.&lt;br /&gt;
&lt;br /&gt;
=Other changes=&lt;br /&gt;
==Course visibility==&lt;br /&gt;
Originally making category hidden forced hiding of course category. Now the category hiding affects only browsing of course, not the actual access. When hiding category all courses are hidden automatically. The new approach improves performance and allows some new scenarios such as hide all courses you are not enrolled in.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Enrolment usage overview]]&lt;br /&gt;
* [[Role archetypes]]&lt;br /&gt;
* [[New permissions evaluation in 2.0]]&lt;br /&gt;
* [[Obsolete:Enrolment rewrite and role tweaks proposal]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Enrolment]]&lt;br /&gt;
[[Category:Roles]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=User_talk:Zak_Fleming&amp;diff=24027</id>
		<title>User talk:Zak Fleming</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=User_talk:Zak_Fleming&amp;diff=24027"/>
		<updated>2009-07-27T23:10:23Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: New page: Zack,  I wonder why you reverted revision 60623 of NTLM_authentication (where I did some formatting fixes). Was there anything wrong with them?  ~~~~&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zack,&lt;br /&gt;
&lt;br /&gt;
I wonder why you reverted revision 60623 of NTLM_authentication (where I did some formatting fixes). Was there anything wrong with them?&lt;br /&gt;
&lt;br /&gt;
[[User:Iñaki Arenaza|Iñaki Arenaza]] 23:10, 27 July 2009 (UTC)&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Git_tips&amp;diff=11320</id>
		<title>Git tips</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Git_tips&amp;diff=11320"/>
		<updated>2009-07-22T20:38:18Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Show how to setup a local share repository to work with&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Many developers find git a useful tool to help them with moodle development, here some tips and workflows can be shared to help others.&lt;br /&gt;
&lt;br /&gt;
== Thorough Resolved Bug QA review with git ==&lt;br /&gt;
&lt;br /&gt;
The power of having fast access to all of moodle commit history means we can search and checkout any point in moodle source code history which allows us to powerfully QA a bug.&lt;br /&gt;
&lt;br /&gt;
Please note this workflow might not be ideal for all scenarios (for example if lots of work has been done in the same area since).&lt;br /&gt;
&lt;br /&gt;
Example Workflow to QA MDL-16600:&lt;br /&gt;
&lt;br /&gt;
First checkout a new branch for us to work on testing the bug in MOODLE_19_STABLE. We can delete this branch later, its less dangerous than playing any of our &#039;live&#039; branches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git checkout -b QA-MDL-16600 origin/MOODLE_19_STABLE&lt;br /&gt;
Branch QA-MDL-16600 set up to track remote branch refs/remotes/origin/MOODLE_19_STABLE.&lt;br /&gt;
Switched to a new branch &amp;quot;QA-MDL-16600&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now search for any commits related to this bug fix:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$  git log --grep=&#039;MDL-16600&#039;&lt;br /&gt;
commit 1c2c8b09469ac27a3829e7267f399356a05b9810&lt;br /&gt;
Author: tjhunt &amp;lt;tjhunt&amp;gt;&lt;br /&gt;
Date:   Fri Sep 26 05:49:06 2008 +0000&lt;br /&gt;
&lt;br /&gt;
    MDL-16600 forcedownload broken for file resources.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to test that these commits fixed the bug, we will revert this commit, and then try to reproduce the reported bug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git revert -n 1c2c8b09469ac27a3829e7267f399356a05b9810 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once we&#039;ve reproduced the problem, we will reset our repository back to HEAD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git reset --hard HEAD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now if the bug is fixed, it can be closed and we can delete our branch:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git branch -D QA-MDL-16600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backporting stuff from cvshead to stable git branches ==&lt;br /&gt;
&lt;br /&gt;
I (Penny) have to do this all the time and it sucks.  So I made a script to make it suck less.&lt;br /&gt;
&lt;br /&gt;
http://cvs.moodle.org/contrib/tools/devtools/bugstogitformatpatch?view=markup&lt;br /&gt;
&lt;br /&gt;
This little perl script takes a list of bug numbers, and generates patches that you can apply with git-am&lt;br /&gt;
&lt;br /&gt;
I backported Tim&#039;s roles UI work and this is how I did it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# make a new branch to work on&lt;br /&gt;
$ git checkout -b mdl19-rolesbackport origin/MOODLE_19_STABLE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now create some file that contains a list of bug numbers... In the case that there&#039;s only one, you can do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ echo MDL-xxxxx | bugstogitformatpatch --otherargs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Else you can do either of:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat myplan | bugstogitformatpatch --otherargs&lt;br /&gt;
$ bugstogitformatpatch --grepfile myplan&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file could be a whole file with documentation and everything, but the script &#039;&#039;&#039;does&#039;&#039;&#039; expect the bug numbers to be one per-line (but accepts other junk on the same line) and start with MDL-xxxx&lt;br /&gt;
&lt;br /&gt;
The script has some other options, like where to put the patches it generates, and what the revlog spec should look like (by default it will just do origin/cvshead, but you can restrict it to a different branch or even abcdefg..12345678 if you want, anything git-log can understand - see man git-rev-parse).&lt;br /&gt;
&lt;br /&gt;
See --help for more information.&lt;br /&gt;
&lt;br /&gt;
Now the script will run and actually much faster than I expected, for Moodle&#039;s entire history.  It will spit out git-format-patch formatted patches, which you can then happily apply with git-am.&lt;br /&gt;
&lt;br /&gt;
TIP:  For a large feature that goes into HEAD, it may happen that someone commits bugfixes to HEAD after you&#039;ve backported it, which you&#039;ll then subsequently want to apply.  To get around this, I did...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git tag rolesbackportedtohead origin/cvshead&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After I was done... then the next time I wanted to run the script, I just used --revlist rolesbackportedtohere..origin/cvshead to only look at patches after the last time.&lt;br /&gt;
&lt;br /&gt;
== Local collaboration ==&lt;br /&gt;
You want to do this...&lt;br /&gt;
&lt;br /&gt;
* git.moodle.org&lt;br /&gt;
** my organisation&#039;s git repository: aka shared repo (pulled from git.moodle.org)&lt;br /&gt;
*** developer 1 (local git)&lt;br /&gt;
*** developer 3 (local git)&lt;br /&gt;
*** etc.&lt;br /&gt;
&lt;br /&gt;
You want to collaboratively develop Moodle stuff pushing and pulling from your local shared repository. On top of that you want the upstream repository itself to pull updates from the upstream git.moodle.org.&lt;br /&gt;
&lt;br /&gt;
Some names used in the examples:&lt;br /&gt;
&lt;br /&gt;
* devel-1: the first developer&lt;br /&gt;
* devel-2: the second developer&lt;br /&gt;
* shared-repo: the name of the shared repository directory&lt;br /&gt;
* git-moodle: the name of the unix group needed to use the shared repository&lt;br /&gt;
&lt;br /&gt;
Some assuptions for the examples:&lt;br /&gt;
&lt;br /&gt;
* Linux/Unix environment&lt;br /&gt;
* All the repositories are on the same machine (if not, only need to change git transports from git:// to git+ssh://, etc.)&lt;br /&gt;
&lt;br /&gt;
Devel-1: Create local repo and configure working environment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/devel-1/dir&lt;br /&gt;
mkdir devel-1.git&lt;br /&gt;
cd devel-1.git&lt;br /&gt;
git init&lt;br /&gt;
git config --global user.name &#039;Devel-1 Real Name&#039;&lt;br /&gt;
git config --global user.email &#039;devel-1@email.address&#039;&lt;br /&gt;
git config --global i18n.commitEncoding &#039;utf8&#039;&lt;br /&gt;
git config --global i18n.logOutputEncoding &#039;utf8&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Get branches from git.moodle.org repo:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git remote add -t cvshead -t MOODLE_19_STABLE -t MOODLE_18_STABLE -m cvshead moodleorg git://git.moodle.org/moodle.git&lt;br /&gt;
git fetch moodleorg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create local (work) branches:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git branch --track cvshead-devel-1 moodleorg/cvshead&lt;br /&gt;
git branch --track mdl19-devel-1 moodleorg/MOODLE_19_STABLE&lt;br /&gt;
git branch --track mdl18-devel-1 moodleorg/MOODLE_18_STABLE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Create local shared repo and configure it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/shared-repo/dir&lt;br /&gt;
mkdir shared-repo.git&lt;br /&gt;
cd shared-repo.git&lt;br /&gt;
git --bare init --shared=all&lt;br /&gt;
chmod g=rwxs,o=rx .          # Give appropiate permissions to users in&lt;br /&gt;
sudo chgrp -R git-moodle .   # group &#039;git-moodle&#039;.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Populate shared repo from local devel-1 repo:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/devel-1/dir/devel-1.git&lt;br /&gt;
git remote add shared-repo /path/to/shared-repo/dir/shared-repo.git&lt;br /&gt;
git push shared-repo +cvshead-devel-1: +mdl19-devel-1: +mdl18-devel-1:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Configure Devel-1 local repo branches to merge the right remote branch when pulling. We need to do this only for the first developer, as the shared repo didn&#039;t exist when we created the branches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/devel-1/dir/devel-1.git&lt;br /&gt;
git config branch.cvshead-devel-1.remote shared-repo&lt;br /&gt;
git config branch.cvshead-devel-1.merge refs/heads/cvshead-devel-1&lt;br /&gt;
git config branch.mdl19-devel-1.remote shared-repo&lt;br /&gt;
git config branch.mdl19-devel-1.merge refs/heads/mdl19-devel-1&lt;br /&gt;
git config branch.mdl18-devel-1.remote shared-repo&lt;br /&gt;
git config branch.mdl18-devel-1.merge refs/heads/mdl18-devel-1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Create Devel-2 local repo and configure working environment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /path/to/devel-2/dir&lt;br /&gt;
git clone -o shared-repo /path/to/shared-repo/dir/shared-repo.git devel-2.git&lt;br /&gt;
cd devel-2.git&lt;br /&gt;
git config --global user.name &#039;Devel-2 Real Name&#039;&lt;br /&gt;
git config --global user.email &#039;devel-2@email.address&#039;&lt;br /&gt;
git config --global i18n.commitEncoding &#039;utf8&#039;&lt;br /&gt;
git config --global i18n.logOutputEncoding &#039;utf8&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Get branches from git.moodle.org repo:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd devel-2.git&lt;br /&gt;
git remote add -t cvshead -t MOODLE_19_STABLE -t MOODLE_18_STABLE -m cvshead moodleorg git://git.moodle.org/moodle.git&lt;br /&gt;
git fetch moodleorg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Create local (work) branches from moodle.org:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git branch --track cvshead-devel-2 moodleorg/cvshead&lt;br /&gt;
git branch --track mdl19-devel-2 moodleorg/MOODLE_19_STABLE&lt;br /&gt;
git branch --track mdl18-devel-2 moodleorg/MOODLE_18_STABLE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
From the shared-repo:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git branch --track cvshead-devel-1 shared-repo/cvshead-devel-1&lt;br /&gt;
git branch --track mdl19-devel-1 shared-repo/mdl19-devel-1&lt;br /&gt;
git branch --track mdl18-devel-1 shared-repo/mdl18-devel-1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Configure local branches to merge the right remote branch when pulling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Nothing to do :-)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can pull and push from any of the configured remote repositories (git.moodle.org and your shared local repo) by specifiying the remote repository name when using &#039;git pull&#039; or &#039;git push&#039;&lt;br /&gt;
&lt;br /&gt;
== More tips please ==&lt;br /&gt;
(Please add your own tips here!)&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Using GIT to backup moodledata]]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=119016 Moodle Development with git]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=124570 Local collaboration and Git - Yeah another git question!!]&lt;br /&gt;
&lt;br /&gt;
[[Category:Git tips]]&lt;br /&gt;
[[Category:Developer tools|Git]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Git_tips&amp;diff=11319</id>
		<title>Git tips</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Git_tips&amp;diff=11319"/>
		<updated>2009-06-02T22:18:05Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Another interesting thread&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Many developers find git a useful tool to help them with moodle development, here some tips and workflows can be shared to help others.&lt;br /&gt;
&lt;br /&gt;
== Thorough Resolved Bug QA review with git ==&lt;br /&gt;
&lt;br /&gt;
The power of having fast access to all of moodle commit history means we can search and checkout any point in moodle source code history which allows us to powerfully QA a bug.&lt;br /&gt;
&lt;br /&gt;
Please note this workflow might not be ideal for all scenarios (for example if lots of work has been done in the same area since).&lt;br /&gt;
&lt;br /&gt;
Example Workflow to QA MDL-16600:&lt;br /&gt;
&lt;br /&gt;
First checkout a new branch for us to work on testing the bug in MOODLE_19_STABLE. We can delete this branch later, its less dangerous than playing any of our &#039;live&#039; branches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git checkout -b QA-MDL-16600 origin/MOODLE_19_STABLE&lt;br /&gt;
Branch QA-MDL-16600 set up to track remote branch refs/remotes/origin/MOODLE_19_STABLE.&lt;br /&gt;
Switched to a new branch &amp;quot;QA-MDL-16600&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now search for any commits related to this bug fix:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$  git log --grep=&#039;MDL-16600&#039;&lt;br /&gt;
commit 1c2c8b09469ac27a3829e7267f399356a05b9810&lt;br /&gt;
Author: tjhunt &amp;lt;tjhunt&amp;gt;&lt;br /&gt;
Date:   Fri Sep 26 05:49:06 2008 +0000&lt;br /&gt;
&lt;br /&gt;
    MDL-16600 forcedownload broken for file resources.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to test that these commits fixed the bug, we will revert this commit, and then try to reproduce the reported bug:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git revert -n 1c2c8b09469ac27a3829e7267f399356a05b9810 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once we&#039;ve reproduced the problem, we will reset our repository back to HEAD:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git reset --hard HEAD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now if the bug is fixed, it can be closed and we can delete our branch:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git branch -D QA-MDL-16600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Backporting stuff from cvshead to stable git branches ==&lt;br /&gt;
&lt;br /&gt;
I (Penny) have to do this all the time and it sucks.  So I made a script to make it suck less.&lt;br /&gt;
&lt;br /&gt;
http://cvs.moodle.org/contrib/tools/devtools/bugstogitformatpatch?view=markup&lt;br /&gt;
&lt;br /&gt;
This little perl script takes a list of bug numbers, and generates patches that you can apply with git-am&lt;br /&gt;
&lt;br /&gt;
I backported Tim&#039;s roles UI work and this is how I did it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# make a new branch to work on&lt;br /&gt;
$ git checkout -b mdl19-rolesbackport origin/MOODLE_19_STABLE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now create some file that contains a list of bug numbers... In the case that there&#039;s only one, you can do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ echo MDL-xxxxx | bugstogitformatpatch --otherargs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Else you can do either of:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat myplan | bugstogitformatpatch --otherargs&lt;br /&gt;
$ bugstogitformatpatch --grepfile myplan&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file could be a whole file with documentation and everything, but the script &#039;&#039;&#039;does&#039;&#039;&#039; expect the bug numbers to be one per-line (but accepts other junk on the same line) and start with MDL-xxxx&lt;br /&gt;
&lt;br /&gt;
The script has some other options, like where to put the patches it generates, and what the revlog spec should look like (by default it will just do origin/cvshead, but you can restrict it to a different branch or even abcdefg..12345678 if you want, anything git-log can understand - see man git-rev-parse).&lt;br /&gt;
&lt;br /&gt;
See --help for more information.&lt;br /&gt;
&lt;br /&gt;
Now the script will run and actually much faster than I expected, for Moodle&#039;s entire history.  It will spit out git-format-patch formatted patches, which you can then happily apply with git-am.&lt;br /&gt;
&lt;br /&gt;
TIP:  For a large feature that goes into HEAD, it may happen that someone commits bugfixes to HEAD after you&#039;ve backported it, which you&#039;ll then subsequently want to apply.  To get around this, I did...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ git tag rolesbackportedtohead origin/cvshead&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After I was done... then the next time I wanted to run the script, I just used --revlist rolesbackportedtohere..origin/cvshead to only look at patches after the last time.&lt;br /&gt;
&lt;br /&gt;
== More tips please ==&lt;br /&gt;
(Please add your own tips here!)&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Using GIT to backup moodledata]]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=119016 Moodle Development with git]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=124570 Local collaboration and Git - Yeah another git question!!]&lt;br /&gt;
&lt;br /&gt;
[[Category:Git tips]]&lt;br /&gt;
[[Category:Developer tools|Git]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9998</id>
		<title>How to apply a patch</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9998"/>
		<updated>2009-03-09T23:57:59Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Add a note about not putting patch.exe in directories with white space in their path&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
This page explains how you can apply a patch file. Patch is a standard format, and there are many options for how to apply one. Pick the one that is easiest for you.&lt;br /&gt;
&lt;br /&gt;
Perhaps most critical is the usage of the -p flag, which tells patch about the relationship between the directory where the patch file is located and the files that will be patched.  See the references below for details and DO NOT assume anything.  &lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Windows using [http://gnuwin32.sourceforge.net/packages/patch.htm gnuwin32]==&lt;br /&gt;
&lt;br /&gt;
* Download and extract patch for windows from [http://gnuwin32.sourceforge.net/packages/patch.htm sourceforge] I placed the patch.exe binary in C:\bin (NOTE: Things are a lot easier if you put it in a directory that doesn&#039;t have white spaces in it.)&lt;br /&gt;
&lt;br /&gt;
* Download and extract Moodle somewhere. eg: C:\moodle&lt;br /&gt;
&lt;br /&gt;
* Download the patch file and place it in the same directory you put Moodle (C:\moodle\password-policy-17.diff)&lt;br /&gt;
&lt;br /&gt;
* Open the patch file with Wordpad, and click &#039;File&#039; &amp;gt;&amp;gt; &#039;Save as...&#039;, choose a different name for the file eg (&#039;mynewpatch.diff&#039;) and &amp;quot;Save as type&amp;quot; &amp;gt;&amp;gt; &#039;Text Document - MS-DOS Format&#039;&lt;br /&gt;
&lt;br /&gt;
* Open up a command text window, and type:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe --dry-run -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
:The number after &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option can vary depending on the patch file, as it depends on the way the patch file was generated. Have a look at the [http://www.rt.com/man/patch.1.html &#039;patch&#039; utility manual page ] to see how the &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option works. You could also have a look at this [http://www.linuxtutorialblog.com/post/introduction-using-diff-and-patch-tutorial diff and patch tutorial].&lt;br /&gt;
* You should get an output similar to this (the names and quantity of patched files vary from patch to patch):&lt;br /&gt;
&lt;br /&gt;
    patching file admin/settings/security.php&lt;br /&gt;
    patching file lang/en_utf8/admin.php&lt;br /&gt;
    patching file lib/moodlelib.php&lt;br /&gt;
    patching file login/change_password.php&lt;br /&gt;
    patching file login/signup.php&lt;br /&gt;
    patching file user/edit.php&lt;br /&gt;
    Hunk #1 succeeded at 430 (offset 2 lines).&lt;br /&gt;
&lt;br /&gt;
:At this stage the patch &amp;lt;b&amp;gt;has not been applied&amp;lt;/b&amp;gt;. We just simulated the application (with the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt; option), to see if we are going to find any problems with it. Before explaining how to actually apply the patch, we are going to talk about what could be wrong, and how to deal with it.&lt;br /&gt;
&lt;br /&gt;
===Potential problems and how to deal with them===&lt;br /&gt;
====Potential problems====&lt;br /&gt;
If everything goes well, the patch will apply cleanly and life should be good! But sometimes the patch will not apply 100% cleanly due to a version mismatch between the original files used to produce the patch file and your local files. In this case, the &#039;patch&#039; command will try to apply as many changes as it can, and will emit some diagnostics describing the problems it encounters. &lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n succeeded...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have been applied correctly although at different line numbers than the original file. If we had actually applied the patch, the &#039;patch&#039; command would have created an additional file for each of the files where the hunk was applied at a different offset, that would be named like the original file with the additional extension &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n failed...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have not applied correctly. In this case the &#039;patch&#039; command would have created two additional files for each of the files where the hunk was not applied correctly, called:&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.orig&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This would be the original file before the patch was applied, just like above.&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.rej&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This file would contain the hunks that could not be applied correctly, so you could inspect them.&lt;br /&gt;
&lt;br /&gt;
====Dealing with potential problems====&lt;br /&gt;
Dealing with the first problem (the offsetted hunks) is trivial: we just need to delete the .orig files once we actually apply the patch.&lt;br /&gt;
&lt;br /&gt;
In the second case (failed hunks), unless you know how to fix the failed hunks by hand, you &amp;lt;b&amp;gt;should not apply&amp;lt;/b&amp;gt; the patch, as that would corrupt your Moodle install. If you want to apply the patch and try to fix the failed hunks by hand, you should use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option. That option automatically makes a backup of every file the patch applies to, with the &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; extension. That would allow you go back to the original files state by simply overwritting the modified files with their &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; backups.&lt;br /&gt;
&lt;br /&gt;
Sometimes, there will be a large difference in line numbers since a patch was generated and the patch will not apply. You can tell patch allow larger differences in line numbers by using the fuzz option &#039;-F&#039; to increase the number of lines difference there can be. For example patch -F 100 would allow 100 lines difference.&lt;br /&gt;
&lt;br /&gt;
===Actually applying the patch===&lt;br /&gt;
Now that we know what could go wrong and how to deal with it, let&#039;s see how to apply the patch. We only need to remove the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
and optionally use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option if we are going to try to fix the failed hunks by hand:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -b -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Linux using &amp;quot;patch&amp;quot;==&lt;br /&gt;
use something like:&lt;br /&gt;
patch -p1 &amp;lt; patchfile.diff&lt;br /&gt;
see [http://linux.about.com/od/commands/l/blcmdl1_patch.htm here] for more details on using Patch in Linux&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
* [[Patch]]&lt;br /&gt;
* [[How_to_create_a_patch]]&lt;br /&gt;
* [http://drupal.org/node/32875 Drupal - using Cygwin in Windows to apply a patch]&lt;br /&gt;
* [http://drupal.org/node/60818 Drupal - how to apply a patch in Mac OS X]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=61379#p286372 moodle post - using gnuwin32 to apply a patch]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorial]]&lt;br /&gt;
&lt;br /&gt;
[[es:Como_aplicar_un_parche]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9996</id>
		<title>How to apply a patch</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9996"/>
		<updated>2008-12-30T22:12:25Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Spanish translation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
This page explains how you can apply a patch file. Patch is a standard format, and there are many options for how to apply one. Pick the one that is easiest for you.&lt;br /&gt;
&lt;br /&gt;
Perhaps most critical is the usage of the -p flag, which tells patch about the relationship between the directory where the patch file is located and the files that will be patched.  See the references below for details and DO NOT assume anything.  &lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Windows using [http://gnuwin32.sourceforge.net/packages/patch.htm gnuwin32]==&lt;br /&gt;
&lt;br /&gt;
* Download and extract patch for windows from [http://gnuwin32.sourceforge.net/packages/patch.htm sourceforge] I placed the patch.exe binary in C:\bin&lt;br /&gt;
&lt;br /&gt;
* Download and extract Moodle somewhere. eg: C:\moodle&lt;br /&gt;
&lt;br /&gt;
* Download the patch file and place it in the same directory you put Moodle (C:\moodle\password-policy-17.diff)&lt;br /&gt;
&lt;br /&gt;
* Open the patch file with Wordpad, and click &#039;File&#039; &amp;gt;&amp;gt; &#039;Save as...&#039;, choose a different name for the file eg (&#039;mynewpatch.diff&#039;) and &amp;quot;Save as type&amp;quot; &amp;gt;&amp;gt; &#039;Text Document - MS-DOS Format&#039;&lt;br /&gt;
&lt;br /&gt;
* Open up a command text window, and type:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe --dry-run -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
:The number after &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option can vary depending on the patch file, as it depends on the way the patch file was generated. Have a look at the [http://www.rt.com/man/patch.1.html &#039;patch&#039; utility manual page ] to see how the &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option works. You could also have a look at this [http://www.linuxtutorialblog.com/post/introduction-using-diff-and-patch-tutorial diff and patch tutorial].&lt;br /&gt;
* You should get an output similar to this (the names and quantity of patched files vary from patch to patch):&lt;br /&gt;
&lt;br /&gt;
    patching file admin/settings/security.php&lt;br /&gt;
    patching file lang/en_utf8/admin.php&lt;br /&gt;
    patching file lib/moodlelib.php&lt;br /&gt;
    patching file login/change_password.php&lt;br /&gt;
    patching file login/signup.php&lt;br /&gt;
    patching file user/edit.php&lt;br /&gt;
    Hunk #1 succeeded at 430 (offset 2 lines).&lt;br /&gt;
&lt;br /&gt;
:At this stage the patch &amp;lt;b&amp;gt;has not been applied&amp;lt;/b&amp;gt;. We just simulated the application (with the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt; option), to see if we are going to find any problems with it. Before explaining how to actually apply the patch, we are going to talk about what could be wrong, and how to deal with it.&lt;br /&gt;
&lt;br /&gt;
===Potential problems and how to deal with them===&lt;br /&gt;
====Potential problems====&lt;br /&gt;
If everything goes well, the patch will apply cleanly and life should be good! But sometimes the patch will not apply 100% cleanly due to a version mismatch between the original files used to produce the patch file and your local files. In this case, the &#039;patch&#039; command will try to apply as many changes as it can, and will emit some diagnostics describing the problems it encounters. &lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n succeeded...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have been applied correctly although at different line numbers than the original file. If we had actually applied the patch, the &#039;patch&#039; command would have created an additional file for each of the files where the hunk was applied at a different offset, that would be named like the original file with the additional extension &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n failed...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have not applied correctly. In this case the &#039;patch&#039; command would have created two additional files for each of the files where the hunk was not applied correctly, called:&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.orig&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This would be the original file before the patch was applied, just like above.&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.rej&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This file would contain the hunks that could not be applied correctly, so you could inspect them.&lt;br /&gt;
&lt;br /&gt;
====Dealing with potential problems====&lt;br /&gt;
Dealing with the first problem (the offsetted hunks) is trivial: we just need to delete the .orig files once we actually apply the patch.&lt;br /&gt;
&lt;br /&gt;
In the second case (failed hunks), unless you know how to fix the failed hunks by hand, you &amp;lt;b&amp;gt;should not apply&amp;lt;/b&amp;gt; the patch, as that would corrupt your Moodle install. If you want to apply the patch and try to fix the failed hunks by hand, you should use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option. That option automatically makes a backup of every file the patch applies to, with the &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; extension. That would allow you go back to the original files state by simply overwritting the modified files with their &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; backups.&lt;br /&gt;
&lt;br /&gt;
Sometimes, there will be a large difference in line numbers since a patch was generated and the patch will not apply. You can tell patch allow larger differences in line numbers by using the fuzz option &#039;-F&#039; to increase the number of lines difference there can be. For example patch -F 100 would allow 100 lines difference.&lt;br /&gt;
&lt;br /&gt;
===Actually applying the patch===&lt;br /&gt;
Now that we know what could go wrong and how to deal with it, let&#039;s see how to apply the patch. We only need to remove the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
and optionally use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option if we are going to try to fix the failed hunks by hand:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -b -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Linux using &amp;quot;patch&amp;quot;==&lt;br /&gt;
use something like:&lt;br /&gt;
patch -p1 &amp;lt; patchfile.diff&lt;br /&gt;
see [http://linux.about.com/od/commands/l/blcmdl1_patch.htm here] for more details on using Patch in Linux&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
&lt;br /&gt;
* [[Patch]]&lt;br /&gt;
* [[How_to_create_a_patch]]&lt;br /&gt;
* [http://drupal.org/node/32875 Drupal - using Cygwin in Windows to apply a patch]&lt;br /&gt;
* [http://drupal.org/node/60818 Drupal - how to apply a patch in Mac OS X]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=61379#p286372 moodle post - using gnuwin32 to apply a patch]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[es:Como_aplicar_un_parche]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9991</id>
		<title>How to apply a patch</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9991"/>
		<updated>2008-08-28T15:45:51Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Added section on potential problems and how to deal with them&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
This page explains how you can apply a patch file. Patch is a standard format, and there are many options for how to apply one. Pick the one that is easiest for you.&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Windows using [http://gnuwin32.sourceforge.net/packages/patch.htm gnuwin32]==&lt;br /&gt;
&lt;br /&gt;
* Download and extract patch for windows from [http://gnuwin32.sourceforge.net/packages/patch.htm sourceforge] I placed the patch.exe binary in C:\bin&lt;br /&gt;
&lt;br /&gt;
* Download and extract Moodle somewhere. eg: C:\moodle&lt;br /&gt;
&lt;br /&gt;
* Download the patch file and place it in the same directory you put Moodle (C:\moodle\password-policy-17.diff)&lt;br /&gt;
&lt;br /&gt;
* Open the patch file with Wordpad, and click &#039;File&#039; &amp;gt;&amp;gt; &#039;Save as...&#039;, choose a different name for the file eg (&#039;mynewpatch.diff&#039;) and &amp;quot;Save as type&amp;quot; &amp;gt;&amp;gt; &#039;Text Document - MS-DOS Format&#039;&lt;br /&gt;
&lt;br /&gt;
* Open up a command text window, and type:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe --dry-run -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
:The number after &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option can vary depending on the patch file, as it depends on the way the patch file was generated. Have a look at the [http://www.rt.com/man/patch.1.html &#039;patch&#039; utility manual page ] to see how the &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option works. You could also have a look at this [http://www.linuxtutorialblog.com/post/introduction-using-diff-and-patch-tutorial diff and patch tutorial].&lt;br /&gt;
* You should get an output similar to this (the names and quantity of patched files vary from patch to patch):&lt;br /&gt;
&lt;br /&gt;
    patching file admin/settings/security.php&lt;br /&gt;
    patching file lang/en_utf8/admin.php&lt;br /&gt;
    patching file lib/moodlelib.php&lt;br /&gt;
    patching file login/change_password.php&lt;br /&gt;
    patching file login/signup.php&lt;br /&gt;
    patching file user/edit.php&lt;br /&gt;
    Hunk #1 succeeded at 430 (offset 2 lines).&lt;br /&gt;
&lt;br /&gt;
:At this stage the patch &amp;lt;b&amp;gt;has not been applied&amp;lt;/b&amp;gt;. We just simulated the application (with the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt; option), to see if we are going to find any problems with it. Before explaining how to actually apply the patch, we are going to talk about what could be wrong, and how to deal with it.&lt;br /&gt;
&lt;br /&gt;
===Potential problems and how to deal with them===&lt;br /&gt;
====Potential problems====&lt;br /&gt;
If everything goes well, the patch will apply cleanly and life should be good! But sometimes the patch will not apply 100% cleanly due to a version mismatch between the original files used to produce the patch file and your local files. In this case, the &#039;patch&#039; command will try to apply as many changes as it can, and will emit some diagnostics describing the problems it encounters. &lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n succeeded...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have been applied correctly although at different line numbers than the original file. If we had actually applied the patch, the &#039;patch&#039; command would have created an additional file for each of the files where the hunk was applied at a different offset, that would be named like the original file with the additional extension &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n failed...&#039;&amp;lt;/tt&amp;gt; messages, the patch would have not applied correctly. In this case the &#039;patch&#039; command would have created two additional files for each of the files where the hunk was not applied correctly, called:&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.orig&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This would be the original file before the patch was applied, just like above.&lt;br /&gt;
** &amp;lt;tt&amp;gt;original-file-name.rej&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This file would contain the hunks that could not be applied correctly, so you could inspect them.&lt;br /&gt;
&lt;br /&gt;
====Dealing with potential problems====&lt;br /&gt;
Dealing with the first problem (the offsetted hunks) is trivial: we just need to delete the .orig files once we actually apply the patch.&lt;br /&gt;
&lt;br /&gt;
In the second case (failed hunks), unless you know how to fix the failed hunks by hand, you &amp;lt;b&amp;gt;should not apply&amp;lt;/b&amp;gt; the patch, as that would corrupt your Moodle install. If you want to apply the patch and try to fix the failed hunks by hand, you should use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option. That option automatically makes a backup of every file the patch applies to, with the &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; extension. That would allow you go back to the original files state by simply overwritting the modified files with their &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt; backups.&lt;br /&gt;
&lt;br /&gt;
===Actually applying the patch===&lt;br /&gt;
Now that we know what could go wrong and how to deal with it, let&#039;s see how to apply the patch. We only need to remove the &amp;lt;tt&amp;gt;&#039;--dry-run&#039;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
and optionally use the &amp;lt;tt&amp;gt;&#039;-b&#039;&amp;lt;/tt&amp;gt; option if we are going to try to fix the failed hunks by hand:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -b -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Linux using &amp;quot;patch&amp;quot;==&lt;br /&gt;
use something like:&lt;br /&gt;
patch -p1 &amp;lt; patchfile.diff&lt;br /&gt;
see [http://linux.about.com/od/commands/l/blcmdl1_patch.htm here] for more details on using Patch in Linux&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[How_to_create_a_patch]]&lt;br /&gt;
* [http://drupal.org/node/32875 Drupal - using Cygwin in Windows to apply a patch]&lt;br /&gt;
* [http://drupal.org/node/60818 Drupal - how to apply a patch in Mac OS X]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=61379#p286372 moodle post - using gnuwin32 to apply a patch]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_create_a_patch&amp;diff=6781</id>
		<title>How to create a patch</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_create_a_patch&amp;diff=6781"/>
		<updated>2008-08-28T14:06:26Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Add sensible options (-N, -r) to the diff command&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have made some changes to the code that you would like to share with the community, particularly if you want to send them to one of the core developers for possible inclusion in Moodle Core, it is very helpful if you can provide them as a patch file. Sometimes also called a diff file.&lt;br /&gt;
&lt;br /&gt;
This page explains how you can make a patch file. Patch is a standard format, and there are many options for how to create one. Pick the one that is easiest for you.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note, I have not been able to test most of these instructions. They are about right, but I am hoping that as people use them, they will fill in any gaps, correct any details, and so on.[[User:Tim Hunt|Tim Hunt]] 08:40, 25 June 2007 (CDT)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Introduction: what does a patch file look like==&lt;br /&gt;
&lt;br /&gt;
This is a simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Index: lang/en_utf8/quiz.php&lt;br /&gt;
===================================================================&lt;br /&gt;
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/quiz.php,v&lt;br /&gt;
retrieving revision 1.57.2.10&lt;br /&gt;
diff -u -r1.57.2.10 quiz.php&lt;br /&gt;
--- lang/en_utf8/quiz.php	29 May 2007 17:47:25 -0000	1.57.2.10&lt;br /&gt;
+++ lang/en_utf8/quiz.php	25 Jun 2007 12:58:34 -0000&lt;br /&gt;
@@ -252,7 +255,6 @@&lt;br /&gt;
 $string[&#039;indivresp&#039;] = &#039;Responses of Individuals to Each Item&#039;;&lt;br /&gt;
 $string[&#039;info&#039;] = &#039;Info&#039;;&lt;br /&gt;
 $string[&#039;introduction&#039;] = &#039;Introduction&#039;;&lt;br /&gt;
-$string[&#039;invalidcategory&#039;] = &#039;Category ID is invalid&#039;;&lt;br /&gt;
 $string[&#039;invalidnumericanswer&#039;] = &#039;One of the answers you entered was not a valid number.&#039;;&lt;br /&gt;
 $string[&#039;invalidnumerictolerance&#039;] = &#039;One of the tolerances you entered was not a valid number.&#039;;&lt;br /&gt;
 $string[&#039;invalidsource&#039;] = &#039;The source is not accepted as valid.&#039;;&lt;br /&gt;
@@ -375,8 +377,10 @@&lt;br /&gt;
 $string[&#039;questiontypesetupoptions&#039;] = &#039;Setup options for question types:&#039;;&lt;br /&gt;
 $string[&#039;quiz:attempt&#039;] = &#039;Attempt quizzes&#039;;&lt;br /&gt;
 $string[&#039;quiz:deleteattempts&#039;] = &#039;Delete quiz attempts&#039;;&lt;br /&gt;
+$string[&#039;quiz:emailconfirmsubmission&#039;] = &#039;Receive own quiz submission notification&#039;;&lt;br /&gt;
+$string[&#039;quiz:emailnotifysubmission&#039;] = &#039;Receive student quiz submission notifications&#039;;&lt;br /&gt;
 $string[&#039;quiz:grade&#039;] = &#039;Grade quizzes manually&#039;;&lt;br /&gt;
-$string[&#039;quiz:ignoretimelimits&#039;] = &#039;Ignores time limit on quizzes&#039;;&lt;br /&gt;
+$string[&#039;quiz:ignoretimelimits&#039;] = &#039;Ignores time limit on quizs&#039;;&lt;br /&gt;
 $string[&#039;quiz:manage&#039;] = &#039;Manage quizzes&#039;;&lt;br /&gt;
 $string[&#039;quiz:preview&#039;] = &#039;Preview quizzes&#039;;&lt;br /&gt;
 $string[&#039;quiz:view&#039;] = &#039;View quiz information&#039;;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At the top it says which file is being affected. Changes to several files can be included in one patch. Lines added are shown with a &#039;+&#039;, lines removed are shown with a &#039;-&#039;, lines changed are shown as the old line being removed and the new one added.&lt;br /&gt;
&lt;br /&gt;
Patch files are good because they only show the changed parts of the file. This has two advantages: it easy to understand the change; and if other parts of the same files change between the patch being made an being used, there is no problem, the patch will still apply.&lt;br /&gt;
&lt;br /&gt;
==Creating a patch using diff==&lt;br /&gt;
&lt;br /&gt;
diff is the a linux command line program, and is where patch files originated. It requires that you have two copies of the code, one with your changes, and one without. Suppose these two copies are in folders called &#039;standard_moodle&#039; and &#039;my_moodle&#039; which are subdirectories of the current folder. Then to create the patch, type:&lt;br /&gt;
&lt;br /&gt;
 diff -Naur standard_moodle my_moodle &amp;gt; patch.txt&lt;br /&gt;
&lt;br /&gt;
==Creating a patch using CVS (command line)==&lt;br /&gt;
&lt;br /&gt;
It is easier if you are using CVS to manage your development, because you don&#039;t need to keep the copy of &#039;standard_moodle&#039;. CVS takes care of that for you. In you workspace (sandbox) type:&lt;br /&gt;
&lt;br /&gt;
 cvs diff -uN &amp;gt; patch.txt&lt;br /&gt;
&lt;br /&gt;
If you have unversioned files to include in your patch, you will notice that the above command simply adds the file&#039;s name to the top of your patch, prefixed with a question mark. This is because your new file is not tagged for adding to the repository. Just do&lt;br /&gt;
&lt;br /&gt;
 cvs add newfile&lt;br /&gt;
&lt;br /&gt;
Then &lt;br /&gt;
&lt;br /&gt;
 cvs diff -uNa &amp;gt; patch.txt&lt;br /&gt;
&lt;br /&gt;
This should add the correct code to the patch, so that someone applying the patch to their working copy will have a new file created at the right place (hopefully!).&lt;br /&gt;
&lt;br /&gt;
If your patch, for some reason, contains a lot of white space changes in many files, you might want to add -Bbw to the diff call. Make sure these changes are really not significant (like adding or removing a space at the end of a line - editors like Eclipse sometimes do this automatically). This can make a patch a lot smaller, and thus easier to review. The complete call would then be &lt;br /&gt;
&lt;br /&gt;
 cvs diff -uNawbB &amp;gt; patch.txt&lt;br /&gt;
&lt;br /&gt;
==Creating a patch using Tortoise CVS==&lt;br /&gt;
&lt;br /&gt;
[http://www.tortoisecvs.org/ Tortoise CVS] is a Windows GUI front end for CVS. To create a patch, right-click on a folder in CVS, and choose &#039;&#039;&#039;CVS -&amp;gt; Make patch ...&#039;&#039;&#039; from the context menu.&lt;br /&gt;
&lt;br /&gt;
==Creating a patch using Eclipse==&lt;br /&gt;
&lt;br /&gt;
See [[Setting_up_Eclipse#Creating_a_patch]]. Eclipse makes creating patches really easy, once you have got it set up correctly.&lt;br /&gt;
&lt;br /&gt;
==Creating a patch using WinMerge==&lt;br /&gt;
&lt;br /&gt;
[http://winmerge.org/ WinMerge] is a nice windows GUI for comparing folders. In this sense it is like the original command-line &#039;diff&#039; program. You need a copy of &#039;standard_moodle&#039; and &#039;my_moodle&#039;. Use &#039;&#039;&#039;File -&amp;gt; Open...&#039;&#039;&#039; to open the two versions for comparison. This will give you a nice view of what you have changed. Then do &#039;&#039;&#039;Tools -&amp;gt; Generate patch ...&#039;&#039;&#039;. In the dialogue box, make sure you select Style: Unified in the Format box.&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[How_to_apply_a_patch]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9990</id>
		<title>How to apply a patch</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=How_to_apply_a_patch&amp;diff=9990"/>
		<updated>2008-08-28T13:56:45Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Improve documentation a bit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
This page explains how you can apply a patch file. Patch is a standard format, and there are many options for how to apply one. Pick the one that is easiest for you.&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Windows using [http://gnuwin32.sourceforge.net/packages/patch.htm gnuwin32]==&lt;br /&gt;
&lt;br /&gt;
* Download and extract patch for windows from [http://gnuwin32.sourceforge.net/packages/patch.htm sourceforge] I placed the patch.exe binary in C:\bin&lt;br /&gt;
&lt;br /&gt;
* Download and extract Moodle somewhere. eg: C:\moodle&lt;br /&gt;
&lt;br /&gt;
* Download the patch file and place it in the same directory you put Moodle (C:\moodle\password-policy-17.diff)&lt;br /&gt;
&lt;br /&gt;
* Open the patch file with Wordpad, and click &#039;File&#039; &amp;gt;&amp;gt; &#039;Save as...&#039;, choose a different name for the file eg (&#039;mynewpatch.diff&#039;) and &amp;quot;Save as type&amp;quot; &amp;gt;&amp;gt; &#039;Text Document - MS-DOS Format&#039;&lt;br /&gt;
&lt;br /&gt;
* Open up a command text window, and type:&lt;br /&gt;
&lt;br /&gt;
    cd \moodle&lt;br /&gt;
    c:\bin\patch.exe -p1 &amp;lt; mynewpatch.diff&lt;br /&gt;
&lt;br /&gt;
:The number after &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option can vary depending on the patch file, as it depends on the way the patch file was generated. Have a look at the [http://www.rt.com/man/patch.1.html &#039;patch&#039; utility manual page ] to see how the &amp;lt;tt&amp;gt;&#039;-p&#039;&amp;lt;/tt&amp;gt; option works. You could also have a look at this [http://www.linuxtutorialblog.com/post/introduction-using-diff-and-patch-tutorial diff and patch tutorial].&lt;br /&gt;
* You should get an output similar to this (the names and quantity of patched files vary from patch to patch):&lt;br /&gt;
&lt;br /&gt;
    patching file admin/settings/security.php&lt;br /&gt;
    patching file lang/en_utf8/admin.php&lt;br /&gt;
    patching file lib/moodlelib.php&lt;br /&gt;
    patching file login/change_password.php&lt;br /&gt;
    patching file login/signup.php&lt;br /&gt;
    patching file user/edit.php&lt;br /&gt;
    Hunk #1 succeeded at 430 (offset 2 lines).&lt;br /&gt;
&lt;br /&gt;
:If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n succeeded...&#039;&amp;lt;/tt&amp;gt; messages, the patch was applied correctly although at different line numbers than the original file. In this case the &#039;patch&#039; command will have created an additional file for each of the files where the hunk was applied at a different offset, that is named like the original file with the additional extension &amp;lt;tt&amp;gt;.orig&amp;lt;/tt&amp;gt;. You can delete those files safely.&lt;br /&gt;
&lt;br /&gt;
:If you get any &amp;lt;tt&amp;gt;&#039;Hunk #n failed...&#039;&amp;lt;/tt&amp;gt; messages, the patch could not be applied correctly. In this case the &#039;patch&#039; command will have created two additional files for each of the files where the hunk was not applied correctly, called:&lt;br /&gt;
:* &amp;lt;tt&amp;gt;original-file-name.orig&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This is the original file before the patch was applied, just like above.&lt;br /&gt;
:* &amp;lt;tt&amp;gt;original-file-name.rej&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; This file contains the hunks that could not be applied correctly, so you can inspect them.&lt;br /&gt;
&lt;br /&gt;
: In this case, unless you know how to fix the failed hunks by hand, you should delete the partially patched file (the one with the original file name) and rename &#039;original-file-name.orig&#039; to &#039;original-file-name&#039;, to restore the original file. You should also delete the .rej file.&lt;br /&gt;
&lt;br /&gt;
==Apply a Patch in Linux using &amp;quot;patch&amp;quot;==&lt;br /&gt;
use something like:&lt;br /&gt;
patch -p1 &amp;lt; patchfile.diff&lt;br /&gt;
see [http://linux.about.com/od/commands/l/blcmdl1_patch.htm here] for more details on using Patch in Linux&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[How_to_create_a_patch]]&lt;br /&gt;
* [http://drupal.org/node/32875 Drupal - using Cygwin in Windows to apply a patch]&lt;br /&gt;
* [http://drupal.org/node/60818 Drupal - how to apply a patch in Mac OS X]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=61379#p286372 moodle post - using gnuwin32 to apply a patch]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Coding&amp;diff=946</id>
		<title>Coding</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Coding&amp;diff=946"/>
		<updated>2008-01-14T23:56:54Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Use escapeshellcmd/escapeshellarg when using shell_exec or other shell related functions.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Any collaborative project needs consistency and stability to stay strong.&lt;br /&gt;
&lt;br /&gt;
These &#039;&#039;&#039;coding guidelines&#039;&#039;&#039; are to provide a goal for all Moodle code to strive to. It&#039;s true that some of the older existing code falls short in a few areas, but it will all be fixed eventually. All new code definitely must adhere to these standards as closely as possible.&lt;br /&gt;
&lt;br /&gt;
==General rules==&lt;br /&gt;
&lt;br /&gt;
# All code files should use the .php extension.&lt;br /&gt;
# All template files should use the .html extension.&lt;br /&gt;
# All text files should use Unix-style text format (most text editors have this as an option).&lt;br /&gt;
# All php tags must be &#039;full&#039; tags like &amp;lt;?php ?&amp;gt; ... not &#039;short&#039; tags like &amp;lt;? ?&amp;gt;.&lt;br /&gt;
# All existing copyright notices must be retained. You can add your own if necessary.&lt;br /&gt;
# Each file should include (require_once) the main config.php file.&lt;br /&gt;
# Any other include/require should use an absolute path beginning with $CFG-&amp;gt;dirroot or  $CFG-&amp;gt;libdir, not relative includes, which [http://uk.php.net/manual/en/function.include.php sometimes behave strangely under PHP].&lt;br /&gt;
# Each file should check that the user is authenticated correctly, using require_login() and has_capability() or require_capability().&lt;br /&gt;
# All access to databases should use the functions in &#039;&#039;lib/dmllib.php&#039;&#039; whenever possible - this allows compatibility across a wide range of databases. You should find that almost anything is possible using these functions. If you must write SQL code then make sure it is: cross-platform; restricted to specific functions within your code (usually a lib.php file); and clearly marked.&lt;br /&gt;
# Don&#039;t create or use global variables except for the standard $CFG, $SESSION, $THEME, $SITE, $COURSE and $USER.&lt;br /&gt;
# All variables should be initialised or at least tested for existence using isset() or empty() before they are used.&lt;br /&gt;
# All strings should be translatable - create new texts in the &amp;quot;lang/en_utf8&amp;quot; files with concise English lowercase names and retrieve them from your code using get_string() or print_string(). Never delete strings to ensure backwards compatibility of the language packs is maintained.&lt;br /&gt;
# All errors should be printed using print_error() to maximise translation and help for users (it automatically links to the docs wiki).&lt;br /&gt;
# All help files should be translatable - create new texts in the &amp;quot;lang/en_utf8/help&amp;quot; directory and call them using helpbutton(). If you need to update a help file:&lt;br /&gt;
#* with a minor change, where an old translation of the file would still make sense, then it&#039;s OK to make the change but you should notify translation AT moodle DOT org.&lt;br /&gt;
#* for a major change you should create a new file by adding an incrementing number (eg filename2.html) so that translators can easily see it&#039;s a new version of the file. Obviously the new code and the help index files should also be modified to point to the newest versions.&lt;br /&gt;
# Incoming data from the browser (sent via GET or POST) automatically has magic_quotes applied (regardless of the PHP settings) so that you can safely insert it straight into the database. All other raw data (from files, or from databases) must be escaped with addslashes() before inserting it into the database. Because this is so often done incorrectly, there is more explanation on this issue of adding and stripping slashes on a [[Developer:Slashes|separate page]].&lt;br /&gt;
# VERY IMPORTANT: All texts within Moodle, especially those that have come from users, should be printed using the format_text() function. This ensures that text is filtered and cleaned correctly. More information can be found on the page about [[Output_functions|output functions]].&lt;br /&gt;
# User actions should be logged using the [[Logs|add_to_log()]] function. These logs are used for [[Settings#Show_activity_reports|activity reports]] and [[Logs]].&lt;br /&gt;
# When generating a HTML link, always make it relative to the full site root, i.e. link to  &#039;&#039;$CFG-&amp;gt;wwwroot/mod/blonk/view.php?id=99&#039;&#039; rather than just &#039;&#039;view.php?id=99&#039;&#039;. This means that your code will work if called by a script in another folder, among other things.&lt;br /&gt;
&lt;br /&gt;
==Coding style==&lt;br /&gt;
&lt;br /&gt;
I know it can be a little annoying to change your style if you&#039;re used to something else, but balance that annoyance against the annoyance of all the people trying later on to make sense of Moodle code with mixed styles. There are obviously many good points for and against any style that people use, but the current style just is, so please stick to it.&lt;br /&gt;
&lt;br /&gt;
1. Indenting should be consistently 4 spaces. Don&#039;t use tabs AT ALL.&lt;br /&gt;
&lt;br /&gt;
2. Variable names should always be easy-to-read, meaningful lowercase English words. If you really need more than one word then run them together, but keep them short as possible. Use plural names for arrays of objects.&lt;br /&gt;
&lt;br /&gt;
      GOOD: $quiz&lt;br /&gt;
      GOOD: $errorstring&lt;br /&gt;
      GOOD: $assignments (for an array of objects)&lt;br /&gt;
      GOOD: $i (but only in little loops)&lt;br /&gt;
&lt;br /&gt;
      BAD: $Quiz&lt;br /&gt;
      BAD: $aReallyLongVariableNameWithoutAGoodReason&lt;br /&gt;
      BAD: $error_string&lt;br /&gt;
&lt;br /&gt;
3. Constants should always be in upper case, and always start with the name of the module. They should have words separated by underscores.&lt;br /&gt;
&lt;br /&gt;
      define(&amp;quot;FORUM_MODE_FLATOLDEST&amp;quot;, 1);&lt;br /&gt;
4. Function names should be simple English lowercase words, and start with the name of the module to avoid conflicts between modules. Words should be separated by underscores. Parameters should always have sensible defaults if possible. Note there is no space between the function name and the following (brackets).&lt;br /&gt;
&lt;br /&gt;
      function forum_set_display_mode($mode=0) {&lt;br /&gt;
          global $USER, $CFG;&lt;br /&gt;
          &lt;br /&gt;
          if ($mode) {&lt;br /&gt;
              $USER-&amp;gt;mode = $mode;&lt;br /&gt;
          } else if (empty($USER-&amp;gt;mode)) {&lt;br /&gt;
              $USER-&amp;gt;mode = $CFG-&amp;gt;forum_displaymode;&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
5. Blocks must always be enclosed in curly braces (even if there is only one line). Moodle uses this style:&lt;br /&gt;
&lt;br /&gt;
      if ($quiz-&amp;gt;attempts) {&lt;br /&gt;
          if ($numattempts &amp;gt; $quiz-&amp;gt;attempts) {&lt;br /&gt;
              error($strtoomanyattempts, &amp;quot;view.php?id=$cm-&amp;gt;id&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
6. Strings should be defined using single quotes where possible, so that [http://php.net/types.string less memory is used].&lt;br /&gt;
&lt;br /&gt;
      $var = &#039;some text without any variables&#039;;&lt;br /&gt;
      $var = &#039;with special characters like a new line &#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
      $var = &#039;a very, very long string with a &#039;.$single.&#039; variable in it&#039;;&lt;br /&gt;
      $var = &#039;some &#039;.$text.&#039; with &#039;.$many.&#039; variables &#039;.$within.&#039; it&#039;;&lt;br /&gt;
&lt;br /&gt;
7. Comments should be added as much as is practical, to explain the code flow and the purpose of functions and variables.&lt;br /&gt;
&lt;br /&gt;
* Every function (and class) should use the popular [http://www.phpdoc.org/ phpDoc format]. This allows code documentation to be generated automatically.&lt;br /&gt;
* Inline comments should use the // style, laid out neatly so that it fits among the code and lines up with it.&lt;br /&gt;
&lt;br /&gt;
      /**&lt;br /&gt;
      * The description should be first, with asterisks laid out exactly&lt;br /&gt;
      * like this example. If you want to refer to a another function,&lt;br /&gt;
      * do it like this: {@link clean_param()}. Then, add descriptions&lt;br /&gt;
      * for each parameter as follows.&lt;br /&gt;
      *&lt;br /&gt;
      * @param int $postid The PHP type is followed by the variable name&lt;br /&gt;
      * @param array $scale The PHP type is followed by the variable name&lt;br /&gt;
      * @param array $ratings The PHP type is followed by the variable name&lt;br /&gt;
      * @return mixed&lt;br /&gt;
      */&lt;br /&gt;
      function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {&lt;br /&gt;
          if (!$ratings) {&lt;br /&gt;
              $ratings = array();     // Initialize the empty array&lt;br /&gt;
              if ($rates = get_records(&amp;quot;forum_ratings&amp;quot;, &amp;quot;post&amp;quot;, $postid)) {&lt;br /&gt;
                  // Process each rating in turn&lt;br /&gt;
                  foreach ($rates as $rate) {&lt;br /&gt;
      ....etc&lt;br /&gt;
&lt;br /&gt;
8. Space should be used liberally - don&#039;t be afraid to spread things out a little to gain some clarity. Generally, there should be one space between brackets and normal statements, but no space between brackets and variables or functions:&lt;br /&gt;
&lt;br /&gt;
      foreach ($objects as $key =&amp;gt; $thing) {&lt;br /&gt;
          process($thing);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      if ($x == $y) {&lt;br /&gt;
          $a = $b;&lt;br /&gt;
      } else if ($x == $z) {&lt;br /&gt;
          $a = $c;&lt;br /&gt;
      } else {&lt;br /&gt;
          $a = $d;&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
9. When making a COPY of an object, always use the php5 clone() function (otherwise you may end up with just a reference to the first object).  Moodle will make sure this works consistently on php4 too.&lt;br /&gt;
&lt;br /&gt;
      BAD:   $b = $a;&lt;br /&gt;
      GOOD:  $b = clone($a);&lt;br /&gt;
&lt;br /&gt;
If the thing you want to copy is not an object, but may contain objects (eg an array of objects) then use fullclone() instead.&lt;br /&gt;
&lt;br /&gt;
==Database structures==&lt;br /&gt;
&lt;br /&gt;
To help you create tables that meet these guidelines, we recommend you use the built in [[XMLDB_defining_an_XML_structure#The_XMLDB_editor|database definition (XMLDB) editor]].&lt;br /&gt;
&lt;br /&gt;
# Every table must have an auto-incrementing id field (INT10) as primary index. (see [[IdColumnReasons]])&lt;br /&gt;
# The main table containing instances of each module must have the same name as the module (eg widget) and contain the following minimum fields:&lt;br /&gt;
#* id - as described above&lt;br /&gt;
#* course - the id of the course that each instance belongs to&lt;br /&gt;
#* name - the full name of each instance of the module&lt;br /&gt;
# Other tables associated with a module that contain information about &#039;things&#039; should be named widget_things (note the plural).&lt;br /&gt;
# Table and column names should avoid using [[Database reserved words|reserved words in any database]]. Please check them before creation.&lt;br /&gt;
# Column names should be always lowercase, simple and short, following the same rules as for variable names.&lt;br /&gt;
# Where possible, columns that contain a reference to the id field of another table (eg widget) should be called widgetid. (Note that this convention is newish and not followed in some older tables)&lt;br /&gt;
# Boolean fields should be implemented as small integer fields (eg INT4) containing 0 or 1, to allow for later expansion of values if necessary.&lt;br /&gt;
# Most tables should have a timemodified field (INT10) which is updated with a current timestamp obtained with the PHP time() function.&lt;br /&gt;
# Always define a default value for each field (and make it sensible)&lt;br /&gt;
# Each table name should start with the database prefix ($CFG-&amp;gt;prefix). In a lot of cases, this is taken care of for you automatically. Also, under Postgres, the name of every index must start with the prefix too.&lt;br /&gt;
# In order to guarantee [[XMLDB problems#Table and column aliases - the AS keyword|cross-db compatibility]] follow these simple rules about the use of the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword (only if you need table/colum aliases, of course):&lt;br /&gt;
#* &#039;&#039;&#039;Don&#039;t use&#039;&#039;&#039; the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword for &#039;&#039;&#039;table aliases&#039;&#039;&#039;.&lt;br /&gt;
#* &#039;&#039;&#039;Do use&#039;&#039;&#039; the &#039;&#039;&#039;AS&#039;&#039;&#039; keyword for &#039;&#039;&#039;column aliases&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Never&#039;&#039;&#039; create UNIQUE KEYs (constraints) at all. Instead use UNIQUE INDEXes. In the future, if we decide to add referential integrity to Moodle and we need UNIQUE KEYs they will be used, but not now. Please note that the XMLDB editor allows you to specify both XMLDB-only UNIQUE and FOREIGN constraints (and that&#039;s good, in order to have the XML well defined) but only underlying INDEXes will be generated. &lt;br /&gt;
# Those XMLDB-only UNIQUE KEYs (read previous point) only must be defined if such field/fields &#039;&#039;&#039;are going to be the target&#039;&#039;&#039; for some (XMLDB-only too) FOREIGN KEY. Else, create them as simple UNIQUE INDEXes.&lt;br /&gt;
# Tables associated &#039;&#039;&#039;with one block&#039;&#039;&#039; must follow this convention with their names: &#039;&#039;&#039;$CFG-&amp;gt;prefix + &amp;quot;block_&amp;quot; + name_of_the_block + anything_else&#039;&#039;&#039;. For example, assuming that $CFG-&amp;gt;prefix is &#039;mdl_&#039;, all the tables for the block &amp;quot;rss_client&amp;quot; must start by &#039;mdl_block_rss_client&#039; (being possible to add more words at the end, i.e. &#039;mdl_block_rss_client_anothertable&#039;...). This rule will be 100% enforced with Moodle 2.0, giving time to developers until then. See [http://tracker.moodle.org/browse/MDL-6786 Task 6786] for more info about this.&lt;br /&gt;
# &#039;&#039;&#039;Never&#039;&#039;&#039; make database changes in the STABLE branches.  If we did, then users upgrading from one stable version to the next would have duplicate changes occurring, which may cause serious errors.&lt;br /&gt;
# When refering to integer variable in SQL queries, do not surround the value in quotes. For example, get_records_select(&#039;question&#039;, &amp;quot;category=$catid&amp;quot;) is right. get_records_select(&#039;question&#039;, &amp;quot;category=&#039;$catid&#039;&amp;quot;) is wrong. It hides bugs where $catid is undefined. ([http://moodle.org/mod/forum/discuss.php?d=80629 This thread explains].)&lt;br /&gt;
&lt;br /&gt;
==Security issues (and handling form and URL data)==&lt;br /&gt;
&lt;br /&gt;
# Do not rely on &#039;register_globals&#039;. Every variable must be properly initialised in every code file. It must be obvious where the variable came from.&lt;br /&gt;
# Initialise all arrays and objects, even if empty. $a = array() or $obj = new stdClass();.&lt;br /&gt;
# Do not use the optional_variable() function (this function is now deprecated). Use the optional_param() function instead. Pick the correct PARAM_XXXX value for the data type you expect.&lt;br /&gt;
# Do not use the require_variable() function (this function is now deprecated). Use the required_param() function instead. Pick the correct PARAM_XXXX value for the data type you expect.&lt;br /&gt;
# Use data_submitted(), with care. Data must still be cleaned before use.&lt;br /&gt;
# Do not use $_GET, $_POST or $_REQUEST. Use the appropriate required_param() or optional_param() appropriate to your need.&lt;br /&gt;
# Do not check for an action using something like if (isset($_GET[&#039;something&#039;])). Use, e.g., $something = optional_param( &#039;something&#039;,-1,PARAM_INT ) and then perform proper test for it being in its expected range of values e.g., if ($something&amp;gt;=0) {....&lt;br /&gt;
# Wherever possible group all your required_param(), optional_param() and other variables initialisation at the beginning of each file to make them easy to find.&lt;br /&gt;
# Use &#039;sesskey&#039; mechanism to protect form handling routines from attack. Basic example of use: when form is generated, include &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;sesskey&amp;quot; value=&amp;quot;&amp;lt;?php echo sesskey(); ?&amp;gt;&amp;quot; /&amp;gt;. When you process the form check with if (!confirm_sesskey()) {error(&#039;Bad Session Key&#039;);}.&lt;br /&gt;
# All filenames must be &#039;cleaned&#039; using the clean_filename() function, if this has not been done already by appropriate use of required_param() or optional_param()&lt;br /&gt;
# Any data read from the database must have [[Developer:Slashes|addslashes()]] applied to it before it can be written back. A whole object of data can be hit at once with addslashes_object().&lt;br /&gt;
# Wherever possible, data to be stored in the database must come from POST data (from a form with method=&amp;quot;POST&amp;quot;) as opposed to GET data (ie, data from the URL line).&lt;br /&gt;
# Do not use data from $_SERVER if you can avoid it. This has portability issues.&lt;br /&gt;
# If it hasn&#039;t been done somewhere else, make sure all data written to the database has been through the clean_param() function using the appropriate PARAM_XXXX for the datatype.&lt;br /&gt;
# If you write custom SQL code, make very sure it is correct. In particular watch out for missing quotes around values. Possible SQL &#039;injection&#039; exploit.&lt;br /&gt;
# Check all data (particularly that written to the database) in every file it is used. Do not expect or rely on it being done somewhere else.&lt;br /&gt;
# Blocks of code to be included should contain a definite PHP structure (e.g, a class declaration, function definition(s) etc.) - straight blocks of code promote uninitialised variable usage.&lt;br /&gt;
# If you need to use shell_exec() (or any other shell invoking function), make sure you clean parameters first with escapeshellcmd()/escapeshellarg (otherwise, we open up for shell injection attacks).&lt;br /&gt;
&lt;br /&gt;
[[Category:Coding]]&lt;br /&gt;
&lt;br /&gt;
[[es:Manual de Estilo de Código]]&lt;br /&gt;
[[ja:コーディング]]&lt;br /&gt;
[[zh:代码指南]]&lt;br /&gt;
[[pl:Kodowanie]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_Eclipse&amp;diff=4931</id>
		<title>Setting up Eclipse</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_Eclipse&amp;diff=4931"/>
		<updated>2007-05-04T23:17:02Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Updated the host to use for anonymous CVS access, to use one of the mirrors.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.eclipse.org/ Eclipse] is an IDE originally designed for Java, but now with plugins for many languages including PHP. It has lots of very powerful features, and it is the editor that some Moodle developers like to use. Other (more) popular choices are vim and emacs.&lt;br /&gt;
&lt;br /&gt;
However, Eclipse is not the easiest program in the world to get started with, so I&#039;m going to take you through it step by step. These instructions assume Eclipse 3.2, the current version at the time of writing. It should not change much between releases.&lt;br /&gt;
&lt;br /&gt;
This article started off as a brain-dump by [[User:Tim Hunt|Tim Hunt]]. Since then, several other people have worked through it and made corrections, so the information here should be pretty accurate.&lt;br /&gt;
&lt;br /&gt;
==Prerequisites==&lt;br /&gt;
&lt;br /&gt;
Eclipse is written in Java, so I recommend getting the latest Java runtime environment from http://java.com/ for maximum speed and reliability.&lt;br /&gt;
&lt;br /&gt;
Eclipse is quite big, so I recommend lots of memory in your computer. I have used it on Windows, MacOS X and Linux, in each case with 1GB of memory, and that is plenty.&lt;br /&gt;
&lt;br /&gt;
==Installing Eclipse==&lt;br /&gt;
&lt;br /&gt;
Go to http://www.eclipse.org/downloads/. Click on the link where it says &#039;&#039;&#039;Download now: Eclipse SDK 3.2&#039;&#039;&#039; It should have automatically detected which platform you are using. Choose a Mirror, and wait for the ~100MB download.&lt;br /&gt;
&lt;br /&gt;
You will notice that what you have got is a zip file (unless your system automatically decompresses it for you).&lt;br /&gt;
&lt;br /&gt;
On Windows, unzip it into &#039;&#039;&#039;C:\Program Files&#039;&#039;&#039; (all the files go into an &#039;&#039;&#039;Eclipse&#039;&#039;&#039; folder there). Then look in the Eclipse folder and drag Eclipse.exe to the Start menu/Desktop/Quicklaunch bar to make a shortcut for starting it.&lt;br /&gt;
&lt;br /&gt;
On MacOS, unzip and copy the Eclipse folder into Applications. Go into the Eclipse folder and drag the Eclipse app to the Dock for ease of launching.&lt;br /&gt;
&lt;br /&gt;
On Linux, unzip somewhere suitable, and make an easy way to launch it.&lt;br /&gt;
&lt;br /&gt;
==The first time you run Eclipse==&lt;br /&gt;
&lt;br /&gt;
The first time you launch Eclipse it does a bit of setup stuff, for instance, it create a &#039;&#039;&#039;workspace&#039;&#039;&#039;. This is where it stores the things you are working on. The default location is sensible on all platforms, so use that. &lt;br /&gt;
&lt;br /&gt;
For some reason, every time you start Eclipse, it asks you which workspace you want to use. I have never seen the need to have more than one, so I recommend turning on the checkbox that says &amp;quot;Don&#039;t ask me this again&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Another thing that happens the first time you run Eclipse is that you arrive at a welcome screen. This has links to various bits of help, which you can read if you like, but you probably don&#039;t need to if you are following these instructions. So find the button on the welcome page that closes it and gets you to the main Eclipse screen.&lt;br /&gt;
&lt;br /&gt;
==Installing the necessary plugins==&lt;br /&gt;
&lt;br /&gt;
By default, Eclipse comes with the Java tools. For everything else you will need to install some plugins.&lt;br /&gt;
&lt;br /&gt;
If you are sitting behind a web proxy, from the &#039;&#039;&#039;Window&#039;&#039;&#039; menu choose &#039;&#039;&#039;Preferences ...&#039;&#039;&#039;. Choose &#039;&#039;&#039;Install/Update&#039;&#039;&#039; from the tree view on the left, and enter the proxy information in the boxes on the right. If you aren&#039;t behind a proxy, ignore this step.&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;Help&#039;&#039;&#039; menu choose &#039;&#039;&#039;Software Updates -&amp;gt; Find and Install&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
On the first screen of the wizard, make sure that &amp;quot;Search for new features to install&amp;quot; is selected, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The next screen is a list of upgrade sites to check. You need to add one to the list, so click the &#039;&#039;&#039;New Remote Site ...&#039;&#039;&#039; Button.&lt;br /&gt;
&lt;br /&gt;
In the pop-up dialog, give the remote site a name like &#039;&#039;&#039;PHPeclipse Update Site&#039;&#039;&#039;; set the URL to http://phpeclipse.sourceforge.net/update/releases/; then click &#039;&#039;&#039;OK&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Back in the wizard, turn on just two things in the box &amp;quot;Sites to include in search&amp;quot;:&lt;br /&gt;
* Your newly created &#039;&#039;&#039;Phpeclipse Update Site&#039;&#039;&#039;; and&lt;br /&gt;
* the one called &#039;&#039;&#039;Callisto Discovery Site&#039;&#039;&#039;.&lt;br /&gt;
Then click &#039;&#039;&#039;Finish&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
It goes off sees what updates are available at those sites. As it does so, it may occasionally pop up a dialog asking you to choose a mirror. Each time, select a sensible one.&lt;br /&gt;
&lt;br /&gt;
Eventually, you get to a new wizard for selecting and installing the updates you want. The ones you want (you may have to search the tree structure) are, &#039;&#039;&#039;PHPeclipse&#039;&#039;&#039; (from your newly created PHPEclipse Update Site) and all the &#039;&#039;&#039;Web Standard Tools (WST)&#039;&#039;&#039; (usually under Callisto Discovery Site --&amp;gt; Web and J2EE Development).&lt;br /&gt;
&lt;br /&gt;
Next, and very importantly, you must click the &#039;&#039;&#039;Select Required&#039;&#039;&#039; button which should resolve dependencies and remove the warning message you are probably worrying about. Then you can click the &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039; button.&lt;br /&gt;
&lt;br /&gt;
Read and agree to all the license agreements. Then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Click &#039;&#039;&#039;Finish&#039;&#039;&#039;, and wait for the plugins to download.&lt;br /&gt;
&lt;br /&gt;
Once the downloads have finished, a warning will pop-up telling you that all the plugins you downloaded are not digitally signed. The Eclipse Foundation build digital signing of plugins into their architecture as a security measure, and then did not sign any of their own plugins! Anyway, click the &#039;&#039;&#039;Install All&#039;&#039;&#039; button.&lt;br /&gt;
&lt;br /&gt;
Finally, a window will pop up asking you to restart Eclipse. Do so.&lt;br /&gt;
&lt;br /&gt;
==Setting the preferences for Moodle development==&lt;br /&gt;
&lt;br /&gt;
Now go to the &#039;&#039;&#039;Window&#039;&#039;&#039; menu, and choose &#039;&#039;&#039;Preferences ...&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The Eclipse preferences are immense, with a tree view on the left, which selects which screen to display on the right. Don&#039;t panic, we&#039;ll guide you through it.&lt;br /&gt;
&lt;br /&gt;
===General settings===&lt;br /&gt;
&lt;br /&gt;
If you have strong feelings about fonts (I would hate to edit code an anything except Andale Mono), choose &#039;&#039;&#039;General -&amp;gt; Appearance -&amp;gt; Colors and Fonts&#039;&#039;&#039; from the tree on the left. Then on the right look under &#039;&#039;&#039;Basic&#039;&#039;&#039; and change &#039;&#039;&#039;Text Font&#039;&#039;&#039;. All the other editor font settings will inherit from this, so this is probably the only one you have to change.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;General -&amp;gt; Content Types&#039;&#039;&#039;, select PHP Source File, and add &#039;&#039;&#039;*.html&#039;&#039;&#039; to the box at the bottom.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;General -&amp;gt; Editors -&amp;gt; File Associations&#039;&#039;&#039;, if it is not already there, add &#039;&#039;&#039;*.php&#039;&#039;&#039; to the top box. With &#039;&#039;&#039;*.php&#039;&#039;&#039; selected in the top box, make sure &#039;&#039;&#039;PHP Editor&#039;&#039;&#039; is set to default in the bottom box. With &#039;&#039;&#039;*.html&#039;&#039;&#039; selected in the top box, select &#039;&#039;&#039;PHP Editor&#039;&#039;&#039; in the bottom box and click the &#039;&#039;&#039;Default&#039;&#039;&#039; button to change it, because in Moodle, most HTML files actually contain PHP code.&lt;br /&gt;
&lt;br /&gt;
If you use a web proxy, enter the details under &#039;&#039;&#039;Internet -&amp;gt; Proxy Settings&#039;&#039;&#039;. (Yes, I know you have entered the somewhere else before. Now you have to enter them again here. I don&#039;t know why. You just do.)&lt;br /&gt;
&lt;br /&gt;
===PHP Settings===&lt;br /&gt;
&lt;br /&gt;
These are all hidden under the &#039;&#039;&#039;PHPeclipse Web Development&#039;&#039;&#039; bit of the tree.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; Browser Preview Defaults&#039;&#039;&#039;, turn off both checkboxes.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; PHP&#039;&#039;&#039;, on the &#039;&#039;&#039;Appearance&#039;&#039;&#039; tab, set &#039;&#039;&#039;Displayed tab width&#039;&#039;&#039; to 4.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; PHP&#039;&#039;&#039;, on the &#039;&#039;&#039;Typing&#039;&#039;&#039; tab, turn off all the options except &#039;&#039;&#039;Pasting for correct indentation&#039;&#039;&#039;, &#039;&#039;&#039;Insert spaces for tab&#039;&#039;&#039; and &#039;&#039;&#039;Close PHPdocs and comments&#039;&#039;&#039; and &#039;&#039;&#039;Remove trailing spaces on editor save&#039;&#039;&#039;. It would be nice to turn on more of these options, but most of the rest don&#039;t work very well.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; PHP -&amp;gt; Formatter&#039;&#039;&#039;, on the &#039;&#039;&#039;New Lines&#039;&#039;&#039; tab, turn on &#039;&#039;&#039;Clear all blank lines&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; PHP -&amp;gt; Formatter&#039;&#039;&#039;, on the &#039;&#039;&#039;Style&#039;&#039;&#039; tab, turn off &#039;&#039;&#039;Indentation is represented by a tab&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; PHP -&amp;gt; Templates&#039;&#039;&#039;, I like to define a new template to help with debugging:&lt;br /&gt;
;Name&lt;br /&gt;
:dump &lt;br /&gt;
;Description&lt;br /&gt;
:Dump a PHP variable&lt;br /&gt;
;Pattern&lt;br /&gt;
&amp;lt;pre&amp;gt;echo &#039;&amp;amp;lt;pre&amp;gt;&#039;; //DONOTCOMMIT&lt;br /&gt;
    print_r(${cursor});&lt;br /&gt;
echo &#039;&amp;amp;lt;/pre&amp;gt;&#039;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
You can do other useful things with templates too.&lt;br /&gt;
&lt;br /&gt;
There is a really stupid bug. Under &#039;&#039;&#039;PHPeclipse Web Development -&amp;gt; Project Defaults&#039;&#039;&#039;, you would like to add &amp;quot;.&amp;quot; to the &#039;&#039;&#039;Include Paths&#039;&#039;&#039;, but you can&#039;t using the GUI. You will have to edit one of the Eclipse config files by hand. So&lt;br /&gt;
# Note down the path to your Eclipse profile. On Windows it will be something like &#039;&#039;&#039;C:/Documents and settings/XXXX/workspace&#039;&#039;&#039;, and on Unixy systems something like &#039;&#039;&#039;~/workspace&#039;&#039;&#039;.&lt;br /&gt;
# Close Eclipse. &lt;br /&gt;
# Open the file &#039;&#039;&#039;net.sourceforge.phpeclipse.ui.prefs&#039;&#039;&#039; that is in the directory &#039;&#039;&#039;(your workspace)/.metadata/.plugins/org.eclipse.core.runtime/.settings&#039;&#039;&#039; in a text editor.&lt;br /&gt;
# Look for a line in the file that starts &#039;&#039;&#039;_php_include_paths=&#039;&#039;&#039; If it is not there, add it at the end.&lt;br /&gt;
# Change this line to say &#039;&#039;&#039;_php_include_paths=.&#039;&#039;&#039;&lt;br /&gt;
# Run Eclipse again.&lt;br /&gt;
&lt;br /&gt;
===CVS Settings===&lt;br /&gt;
&lt;br /&gt;
These are all hidden under the &#039;&#039;&#039;Team&#039;&#039;&#039; bit of the tree.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Team -&amp;gt; CVS -&amp;gt; SSH2 Connection Method&#039;&#039;&#039;, you can set up a public/private key pair. If you do this, you won&#039;t have to keep typing your Sourceforge password when doing CVS operations. See http://sourceforge.net/docs/F02/ for the instructions of what you have to do at the Sourceforge end to make this work. That should make it clear what you have to do in Eclipse.&lt;br /&gt;
&lt;br /&gt;
The rest of the ones in this section are personal preferences, but I recommend them because the default settings are very irritating.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Team&#039;&#039;&#039;, set &#039;&#039;&#039;Perspectives&#039;&#039;&#039; to &#039;&#039;&#039;None&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Team -&amp;gt; CVS -&amp;gt; Annotate&#039;&#039;&#039; set &#039;&#039;&#039;Use Quick Diff annotate mode for local file annotations&#039;&#039;&#039; to &#039;&#039;&#039;Yes&#039;&#039;&#039;, and &#039;&#039;&#039;Open perspective after a &#039;Show Annotations&#039; operation&#039;&#039;&#039; to &#039;&#039;&#039;No&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Team -&amp;gt; CVS -&amp;gt; Label Decorations&#039;&#039;&#039;, switch to the &#039;&#039;&#039;Icon Decorations&#039;&#039;&#039; tab and turn on all the settings, and then on the &#039;&#039;&#039;Text Decorations&#039;&#039;&#039; tab change both &#039;&#039;&#039;File Decoration&#039;&#039;&#039; and &#039;&#039;&#039;Folder Decoration&#039;&#039;&#039; to be just &#039;&#039;&#039;{name}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Web and XML settings===&lt;br /&gt;
&lt;br /&gt;
Foreach XXX in CSS, HTML, Javascript, XML:&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Web and XML -&amp;gt; XXX Files -&amp;gt;XXX Source&#039;&#039;&#039;, choose &#039;&#039;&#039;Indent using spaces&#039;&#039;&#039; and &#039;&#039;&#039;indentation size&#039;&#039;&#039; 4.&lt;br /&gt;
&lt;br /&gt;
==Checking out the Moodle code==&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;File&#039;&#039;&#039; menu, choose &#039;&#039;&#039;New -&amp;gt; Project ...&#039;&#039;&#039;, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In the wizard that pops up, choose &#039;&#039;&#039;CVS -&amp;gt; Projects from CVS&#039;&#039;&#039;, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;&#039;Create a new repository location&#039;&#039;&#039;, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Fill in&lt;br /&gt;
&amp;lt;div style=&amp;quot;float: right; border: 1px solid orange; padding: 0 1em;&amp;quot;&amp;gt;&lt;br /&gt;
For anonymous CVS access use&lt;br /&gt;
;Host&lt;br /&gt;
:XX.cvs.moodle.org&lt;br /&gt;
where XX.cvs.moodle.org is one of [[CVS_for_Administrators#CVS_Servers|these mirrors]]&lt;br /&gt;
;Repository path&lt;br /&gt;
:/cvsroot/moodle&lt;br /&gt;
;User&lt;br /&gt;
:anonymous&lt;br /&gt;
;Password&lt;br /&gt;
:(leave blank)&lt;br /&gt;
;Connection type&lt;br /&gt;
:pserver&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
;Host&lt;br /&gt;
:moodle.cvs.sourceforge.net&lt;br /&gt;
;Repository path&lt;br /&gt;
:/cvsroot/moodle&lt;br /&gt;
;User&lt;br /&gt;
:(your sourceforge username)&lt;br /&gt;
;Password&lt;br /&gt;
:(if you set up the SSH2 key thing in preferences, leave this blank, otherwise, type in your sourceforge password.)&lt;br /&gt;
;Connection type&lt;br /&gt;
:extssh&lt;br /&gt;
(CVS experts, if you are confused by that last one, know it is an Eclipse-specific thing.) Then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
On the next screen of the Wizard, choose &#039;&#039;&#039;Use an existing module&#039;&#039;&#039;. Wait a moment, then select &#039;&#039;&#039;moodle&#039;&#039;&#039; from the list. Click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
On the next screen, make sure the option &#039;&#039;&#039;Check out as a project configured using the New Project Wizard&#039;&#039;&#039; is selected, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Click &#039;&#039;&#039;Refresh Tags&#039;&#039;&#039;, then choose the branch you want. For now leave it set to &#039;&#039;&#039;HEAD&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Click &#039;&#039;&#039;Finish&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now you  will find yourself back at the start of the &#039;&#039;&#039;New Project&#039;&#039;&#039; Wizard. This is because of the option you chose three paragraphs ago. This time you should select &#039;&#039;&#039;PHP -&amp;gt; PHP Project&#039;&#039;&#039;, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make up a project name. &#039;&#039;&#039;moodle&#039;&#039;&#039; would be sensible.&lt;br /&gt;
&lt;br /&gt;
Click &#039;&#039;&#039;Finish&#039;&#039;&#039;, and wait while all the moodle files are checked out of CVS.&lt;br /&gt;
&lt;br /&gt;
Once it has finished, it will probably ask you if you want to switch to the PHP perspective. Answer &#039;&#039;&#039;Yes&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you also need the 1.6 stable branch, or another branch, repeat all the other steps with a few changes:&lt;br /&gt;
* This time you can choose &#039;&#039;&#039;Use and existing repository location&#039;&#039;&#039; instead of typing all the sourceforge CVS details again.&lt;br /&gt;
* Select the appropriate branch.&lt;br /&gt;
* Use a different project name.&lt;br /&gt;
&lt;br /&gt;
==Let your development web server know where your files are==&lt;br /&gt;
&lt;br /&gt;
Either by editing you web server&#039;s config files, or using a symbolic link. Make sure your webserver can see your new working set of files at a sensible URL, so you can test the code you are working on.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Quick tour of some cool features, and remaining configuration changes==&lt;br /&gt;
&lt;br /&gt;
I find the default workbench setup is pretty good. Here is a quick guide to some of the bits.&lt;br /&gt;
&lt;br /&gt;
===Navigator===&lt;br /&gt;
&lt;br /&gt;
To the left is the &#039;&#039;&#039;Navigator&#039;&#039;&#039;. This is a tree view of all your files. If you double-click on a file, it opens in the editor in the middle. Try opening &#039;&#039;&#039;course/lib.php&#039;&#039;&#039; now. You will notice that it comes up nicely syntax-hightlighted.&lt;br /&gt;
&lt;br /&gt;
===Error highlighting===&lt;br /&gt;
&lt;br /&gt;
In the middle of the file, just type any old text, for example &amp;quot;I like Eclipse&amp;quot;. Obviously, this is not valid PHP syntax, and Eclipse will notice this, and put a red underline under it. Also, by the scrollbar is a ruler with a red mark in it to show the error.&lt;br /&gt;
&lt;br /&gt;
You will see some yellow marks lower down the ruler. There are warnings. Click on one, and you will be taked to where that warning is in the file. Hover your mouse over the warning, and you will get a tooltip explaining what the problem might be.&lt;br /&gt;
&lt;br /&gt;
Save the edited file. (Don&#039;t worry that it is broken, we&#039;ll clean up the mess later.) Notice that a red error marker is added to the file in the navigator, so you can see that there is a problem. Also, error markers are added to the course folder, and the whole project, so you could see there was an error even if the navigator tree was collapsed.&lt;br /&gt;
&lt;br /&gt;
You will probably find lots of warnings that the config.php file can&#039;t be found. In the navigator, find the file &#039;&#039;&#039;config-dist.php&#039;&#039;&#039;. Do &#039;&#039;&#039;Copy&#039;&#039;&#039; then &#039;&#039;&#039;Paste&#039;&#039;&#039; and choose to call the new file &#039;&#039;&#039;config.php&#039;&#039;&#039;. Edit this new config.php as normal. You should fine that most of the include file warnings have gone now.&lt;br /&gt;
&lt;br /&gt;
Notice also that there is another marker on each file icon. A little yellow cylinder on most files, but a white-on-brown star on the one you have edited. This is telling you the CVS status of each file. The brown stars are changes you have made but not checked in yet.&lt;br /&gt;
&lt;br /&gt;
===Outline===&lt;br /&gt;
&lt;br /&gt;
Over to the right is the Outline view. This shows a list of functions and classes defined in this file. By default, they are listed in the same order as in the file, but if you click on the &#039;&#039;&#039;az&#039;&#039;&#039; toolbar button, they are sorted into alphabetical order.&lt;br /&gt;
&lt;br /&gt;
Click on the function name &#039;&#039;&#039;add_course_module&#039;&#039;&#039; in the Outline. You will see that the editor scrolls to the definition of that function.&lt;br /&gt;
&lt;br /&gt;
===Code navigation===&lt;br /&gt;
&lt;br /&gt;
In that function, hover the mouse pointer over the function name &#039;&#039;&#039;insert_record&#039;&#039;&#039;. After a while, the documentation for that function will appear in a big tooltip.&lt;br /&gt;
&lt;br /&gt;
Hold down CTRL, move the mouse pointer over the function name &#039;&#039;&#039;insert_record&#039;&#039;&#039;, then click. Eclipse should load &#039;&#039;&#039;dmllib.php&#039;&#039;&#039;, and scroll you to where this function is defined.&lt;br /&gt;
&lt;br /&gt;
In the main Eclipse toolbar, there are forward and back arrows like in a web browser. Click back now to get back to &#039;&#039;&#039;course/lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Open resource===&lt;br /&gt;
&lt;br /&gt;
From the &#039;&#039;&#039;Navigate&#039;&#039;&#039; menu, choose &#039;&#039;&#039;Open Resource...&#039;&#039;&#039;. In the dialog that pops up, start typing a filename for instance type &#039;&#039;&#039;moodlel&#039;&#039;&#039;. In the box in the middle of the dialog, you will see it list all the files in the project whose names start that way. At the bottom is a box which lists the different folders that contain a file with that name. This can be a very quick way of opening files with fairly unique names like moodlelib.php, without having to click through the levels of the navigator tree. Of course, it is not so useful for an index.php file! Click OK now to open moodlelib.php. (It would actually work if you just did CTRL + Shift + R, moodlel, Enter.)&lt;br /&gt;
&lt;br /&gt;
===Multi-file search===&lt;br /&gt;
&lt;br /&gt;
Scroll down moodlelib a little bit, and double click on the name of the constant &#039;&#039;&#039;MOODLE_INTERNAL&#039;&#039;&#039; where it is defined, so that the text is selected. Then, from the &#039;&#039;&#039;Search&#039;&#039;&#039; menu, choose &#039;&#039;&#039;Search...&#039;&#039;&#039;. Notice that the &#039;&#039;&#039;Containing text&#039;&#039;&#039; box has already been filled in for you with the text you just selected. Of course you can just type text into this box without selecting it first. Notice that you can do regular expression searches, but leave that turned off for now. In the &#039;&#039;&#039;File name patterns&#039;&#039;&#039; box type &#039;&#039;&#039;*.css, *.html, *.inc, *.js, *.php, *.xml&#039;&#039;&#039;. (This is the most useful general setting for working on moodle. Eclipse will remember this setting, so you only have to enter it once.) Click &#039;&#039;&#039;Search&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The search results will appear in a new view underneath the editor. That view has a toolbar with yellow up and down arrows. Click the down arrow a few times and it will take you to the first few matches in the code, opening the relevant files as necessary.&lt;br /&gt;
&lt;br /&gt;
===Synchronize view===&lt;br /&gt;
&lt;br /&gt;
I think this is my favorite feature. From the &#039;&#039;&#039;Window&#039;&#039;&#039; menu, select &#039;&#039;&#039;Show View -&amp;gt; Other...&#039;&#039;&#039;. In the dialog that pops up, select &#039;&#039;&#039;Team -&amp;gt; Synchronize&#039;&#039;&#039;, then click &#039;&#039;&#039;OK&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This opens the Synchronize view below the editor. The view has a toolbar. Click on the first toolbar button, which pops up the Synchronize wizard.&lt;br /&gt;
&lt;br /&gt;
On the first screen, there will probably only be one option: &#039;&#039;&#039;CVS&#039;&#039;&#039;. Make sure that is selected, then click &#039;&#039;&#039;Next &amp;gt;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Under &#039;&#039;&#039;Scope&#039;&#039;&#039;, choose &#039;&#039;&#039;Workspace&#039;&#039;&#039;, then click &#039;&#039;&#039;Finish&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Wait while it talks to the CVS server. After a while, you will see that the Synchronize view lists course/lib.php, and something called &#039;&#039;&#039;.project.... That is, it is listing just the files you have edited, but not checked in yet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;.project&#039;&#039;&#039; is something that belongs to Eclipse that we don&#039;t care about. So select it and bring up the context menu, and choose &#039;&#039;&#039;Add to .cvsignore...&#039;&#039;&#039;. In the dialog that pops up, choose the top option, then click &#039;&#039;&#039;OK&#039;&#039;&#039;. Then you will find the Synchronize view shows you a &#039;&#039;&#039;.cvsignore&#039;&#039;&#039; file that you aren&#039;t interested in, so add that to .cvsignore too!&lt;br /&gt;
&lt;br /&gt;
If you double-click on &#039;&#039;&#039;course/lib.php&#039;&#039;&#039; here, you will see that it opens the compare editor, which is a nice graphical display of the changes in this file.&lt;br /&gt;
&lt;br /&gt;
If you select a file or files here, then bring up the context menu, you will see the option to &#039;&#039;&#039;Commit...&#039;&#039;&#039; the changes. (But don&#039;t do that now!). This is the easiest way to commit things in Eclipse.&lt;br /&gt;
&lt;br /&gt;
However, our changes were rubbish, so we want to undo them. So open the context menu again, and choose &#039;&#039;&#039;Override and Update&#039;&#039;&#039;. This checks a clean copy of the file out of CVS, removing our changes.&lt;br /&gt;
&lt;br /&gt;
Note that the easiest way to do an ordinary CVS Update is to select the top-level project-folder in the Navigator view on the left, open the context menu, and choose &#039;&#039;&#039;Team -&amp;gt; Update&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all the really important features. I sure you can learn everything else on your own. An you could always read the built in help!&lt;br /&gt;
&lt;br /&gt;
===Creating a patch===&lt;br /&gt;
&lt;br /&gt;
In the synchronise view, right click on an item (file or folder) and choose &#039;&#039;&#039;Create Patch...&#039;&#039;&#039;. Or in the navigator, right click on an item and choose &#039;&#039;&#039;Team -&amp;gt; Create Patch...&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This brings up a two-page wizard. On the first page you can select where you want the patch made. For small patches it can be useful to create them on the clipboard, but normally you will want to save them in a file.&lt;br /&gt;
&lt;br /&gt;
On the second page, you can set some options, but normally you don&#039;t need to change the defaults which are &#039;&#039;&#039;Unified&#039;&#039;&#039; diff format, and Patch root set to &#039;&#039;&#039;Workspace&#039;&#039;&#039;. Well, sometimes it is helpful to change the second one to &#039;&#039;&#039;Project&#039;&#039;&#039; but it is not important.&lt;br /&gt;
&lt;br /&gt;
There is a corresponding apply patch wizard that you can use to apply a patch to a project.&lt;br /&gt;
&lt;br /&gt;
==Related Links==&lt;br /&gt;
&lt;br /&gt;
There is an excellent series of articles published by IBM on using Eclipse for Drupal developement here : [http://www-128.ibm.com/developerworks/ibm/osource/index.html Using open source software to design, develop, and deploy a collaborative Web site Tools and techniques for getting relatively complicated Web sites up and running quickly].&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3237</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3237"/>
		<updated>2006-11-22T13:56:29Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples authentication instances (instances for short) of the same source type (LDAP, database, etc)&lt;br /&gt;
* Each instance has its own configuration&lt;br /&gt;
* The order in which we try the instances is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source (and thus each instance) has at least the auth_user_login function, like now. (this may change to class function user_login() once Jonathan Harker and Martin Langhoff work in multi-authentication is merged).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each instance in the configured order.&lt;br /&gt;
* For each instance, we call auth_user_login() (or user_login()) with the user credentials, and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the instances returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql syntax omitted for shortness)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `isinternal` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;1&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types (sources) present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;manual&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;isinternal&#039; if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn&#039;t depend on any external entity to provide authentication. Tipically this is for &#039;manual&#039;, &#039;email&#039; and &#039;none&#039;.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;manual&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;manual&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;manual&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `enabled` tinyint(1) NOT NULL default &#039;1&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to use each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
* &#039;enabled&#039;: if this instance is enabled (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ANSWER TO BIG QUESTION&#039;&#039;&#039;: After talking with Martin Langhoff at MoodleMoot Spain &#039;06, this is clearly a Bad(tm) thing. If we allow users to &amp;quot;float&amp;quot; between authentication instances, things like auth_ldap_sync_users.php could break havoc, deleting users it doesn&#039;t know about in this auth_instance (but perfectly valid in other auth_instance&#039;s). So storing the auth_instance &#039;id&#039; in prefix_user and using it accordingly is The Right Thing(tm).&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Multiple instances login: If we use multiple Moodle instances, from my point it means that a user can have access to several instances. So  it will be a good idea to think about a kind of Moodle portal that shows all the instances a user can access. &lt;br /&gt;
#:: I hadn&#039;t thought about this when posting the original questions, because I was thinking about one Moodle site and multiple authentication sources (our problem at the moment), but with [[Community_hub|Moodle Network]] around the corner, this is a real issue. Well thought out Hélène :-) -- [[User:Iñaki Arenaza|Iñaki Arenaza]] 07:56, 22 November 2006 (CST)&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3235</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3235"/>
		<updated>2006-09-30T21:24:19Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: By default, all authentication types can have multiple instances.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples authentication instances (instances for short) of the same source type (LDAP, database, etc)&lt;br /&gt;
* Each instance has its own configuration&lt;br /&gt;
* The order in which we try the instances is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source (and thus each instance) has at least the auth_user_login function, like now. (this may change to class function user_login() once Jonathan Harker and Martin Langhoff work in multi-authentication is merged).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each instance in the configured order.&lt;br /&gt;
* For each instance, we call auth_user_login() (or user_login()) with the user credentials, and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the instances returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql syntax omitted for shortness)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `isinternal` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;1&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types (sources) present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;manual&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;isinternal&#039; if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn&#039;t depend on any external entity to provide authentication. Tipically this is for &#039;manual&#039;, &#039;email&#039; and &#039;none&#039;.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;manual&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;manual&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;manual&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `enabled` tinyint(1) NOT NULL default &#039;1&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to use each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
* &#039;enabled&#039;: if this instance is enabled (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ANSWER TO BIG QUESTION&#039;&#039;&#039;: After talking with Martin Langhoff at MoodleMoot Spain &#039;06, this is clearly a Bad(tm) thing. If we allow users to &amp;quot;float&amp;quot; between authentication instances, things like auth_ldap_sync_users.php could break havoc, deleting users it doesn&#039;t know about in this auth_instance (but perfectly valid in other auth_instance&#039;s). So storing the auth_instance &#039;id&#039; in prefix_user and using it accordingly is The Right Thing(tm).&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3234</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3234"/>
		<updated>2006-09-28T21:04:22Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Minor corrections and &amp;#039;enabled&amp;#039; field addition to prefix_auth_instance&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples authentication instances (instances for short) of the same source type (LDAP, database, etc)&lt;br /&gt;
* Each instance has its own configuration&lt;br /&gt;
* The order in which we try the instances is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source (and thus each instance) has at least the auth_user_login function, like now. (this may change to class function user_login() once Jonathan Harker and Martin Langhoff work in multi-authentication is merged).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each instance in the configured order.&lt;br /&gt;
* For each instance, we call auth_user_login() (or user_login()) with the user credentials, and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the instances returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql syntax omitted for shortness)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `isinternal` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types (sources) present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;manual&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;isinternal&#039; if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn&#039;t depend on any external entity to provide authentication. Tipically this is for &#039;manual&#039;, &#039;email&#039; and &#039;none&#039;.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;manual&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;manual&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;manual&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `enabled` tinyint(1) NOT NULL default &#039;1&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to use each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
* &#039;enabled&#039;: if this instance is enabled (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ANSWER TO BIG QUESTION&#039;&#039;&#039;: After talking with Martin Langhoff at MoodleMoot Spain &#039;06, this is clearly a Bad(tm) thing. If we allow users to &amp;quot;float&amp;quot; between authentication instances, things like auth_ldap_sync_users.php could break havoc, deleting users it doesn&#039;t know about in this auth_instance (but perfectly valid in other auth_instance&#039;s). So storing the auth_instance &#039;id&#039; in prefix_user and using it accordingly is The Right Thing(tm).&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3232</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3232"/>
		<updated>2006-09-20T21:00:14Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Don&amp;#039;t allow users to &amp;quot;float&amp;quot; between auth instances&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples sources of the same type (LDAP, database, etc)&lt;br /&gt;
* Each source has its own configuration&lt;br /&gt;
* The order in which we try the sources is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source has at least the auth_user_login function (like now).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each source in the configured order.&lt;br /&gt;
* For each order, we call auth_user_login with the user credentials and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the sources returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql gurus please adjust definition ;-)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `isinternal` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;internal&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;isinternal&#039; if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn&#039;t depend on any external entity to provide authentication. Tipically this is for &#039;manual&#039;, &#039;email&#039; and &#039;none&#039;.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;internal&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;internal&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;internal&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to user each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ANSWER TO BIG QUESTION&#039;&#039;&#039;: After talking with Martin Langhoff at MoodleMoot Spain &#039;06, this is clearly a Bad(tm) thing. If we allow users to &amp;quot;float&amp;quot; between authentication instances, things like auth_ldap_sync_users.php could break havoc, deleting users it doesn&#039;t know about in this auth_instance (but perfectly valid in other auth_instance&#039;s). So storing the auth_instance &#039;id&#039; in prefix_user and using it accordingly is The Right Thing(tm).&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=UK_MoodleMoot_06_hackfest&amp;diff=4196</id>
		<title>UK MoodleMoot 06 hackfest</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=UK_MoodleMoot_06_hackfest&amp;diff=4196"/>
		<updated>2006-07-07T10:20:50Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: /* Performance profiling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Monday 24th July, 2006&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Welcommen zum Hackfest&#039;&#039; (OK - I&#039;ve been watching too much WorldCup on TV). &lt;br /&gt;
&lt;br /&gt;
The first MoodleMoot hackfest is nearly upon us... and we don&#039;t have an agenda!&lt;br /&gt;
&lt;br /&gt;
This is an open source agenda for the hackfest. We&#039;ll have a day before the Moot to geek out on some code, maybe develop a feature or two, fix some bugs and generally make our favorite learning system a happier place. But I leave it up to you to tell me exactly what we should do. We have four or five rooms with internet connections, a few projectors, and I&#039;ll try to get pizza. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by brainstorming some ideas here for a few days. If someone posts something you&#039;re interested in, put your name under it as a vote. The top votes become our central organizing ideas. For example&lt;br /&gt;
&lt;br /&gt;
==1 Bug fixing==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s spend a few hours and hunt down as many outstanding bugs in 1.6 as possible. Bounties for most bugs killed, trickiest bug killed, and most unusual bug killed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m Interested:&#039;&#039;&lt;br /&gt;
# Jason Cole&lt;br /&gt;
# skodak&lt;br /&gt;
# martin langhoff (auth &amp;amp; enrolment specifically).&lt;br /&gt;
# Martin Dougiamas&lt;br /&gt;
&lt;br /&gt;
(iarenaza) I won&#039;t be there, but here are a couple of bugs for Martin L., related to auth: #4648 and #5373. Very easy to fix :-)&lt;br /&gt;
&lt;br /&gt;
==2 What next for the quiz module?==&lt;br /&gt;
&lt;br /&gt;
If any other quizzy people are there, we should have a talk about where we see the quiz module going.&lt;br /&gt;
&lt;br /&gt;
I/the OU have the following priorities:&lt;br /&gt;
&lt;br /&gt;
# Make question type plugins really plug-in-able. At the moment there are some limitations:&lt;br /&gt;
#* All the lang strings are still in lang/en_utf8/quiz.php.&lt;br /&gt;
#* qtype plugins cannot easily feed CSS and Javascript into the page.&lt;br /&gt;
#* pluggable qtypes and pluggable inport/export filters don&#039;t play nicely together.&lt;br /&gt;
# Write some new question types.&lt;br /&gt;
# Make some improvements to existing question types.&lt;br /&gt;
# Get RQP working again, so our in-house question engine can talk to Moodle.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m Interested:&#039;&#039;&lt;br /&gt;
# Tim Hunt&lt;br /&gt;
&lt;br /&gt;
==Performance profiling==&lt;br /&gt;
&lt;br /&gt;
Pick a (memory|database) hog and put it on a diet. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m interested&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# martin langhoff&lt;br /&gt;
&lt;br /&gt;
(iarenaza) Once again, I won&#039;t be there, but here&#039;s an unfixed bug in 1.6.x and HEAD (was fixed in 1.5.x, but not applied to HEAD at the moment): bug #4591&lt;br /&gt;
&lt;br /&gt;
==Add your suggestion here ...==&lt;br /&gt;
&lt;br /&gt;
Go on, you know you want to.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [http://moodlemoot.org/ http://moodlemoot.org/]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=UK_MoodleMoot_06_hackfest&amp;diff=4195</id>
		<title>UK MoodleMoot 06 hackfest</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=UK_MoodleMoot_06_hackfest&amp;diff=4195"/>
		<updated>2006-07-07T10:18:51Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: /* 1 Bug fixing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Monday 24th July, 2006&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Welcommen zum Hackfest&#039;&#039; (OK - I&#039;ve been watching too much WorldCup on TV). &lt;br /&gt;
&lt;br /&gt;
The first MoodleMoot hackfest is nearly upon us... and we don&#039;t have an agenda!&lt;br /&gt;
&lt;br /&gt;
This is an open source agenda for the hackfest. We&#039;ll have a day before the Moot to geek out on some code, maybe develop a feature or two, fix some bugs and generally make our favorite learning system a happier place. But I leave it up to you to tell me exactly what we should do. We have four or five rooms with internet connections, a few projectors, and I&#039;ll try to get pizza. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s start by brainstorming some ideas here for a few days. If someone posts something you&#039;re interested in, put your name under it as a vote. The top votes become our central organizing ideas. For example&lt;br /&gt;
&lt;br /&gt;
==1 Bug fixing==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s spend a few hours and hunt down as many outstanding bugs in 1.6 as possible. Bounties for most bugs killed, trickiest bug killed, and most unusual bug killed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m Interested:&#039;&#039;&lt;br /&gt;
# Jason Cole&lt;br /&gt;
# skodak&lt;br /&gt;
# martin langhoff (auth &amp;amp; enrolment specifically).&lt;br /&gt;
# Martin Dougiamas&lt;br /&gt;
&lt;br /&gt;
(iarenaza) I won&#039;t be there, but here are a couple of bugs for Martin L., related to auth: #4648 and #5373. Very easy to fix :-)&lt;br /&gt;
&lt;br /&gt;
==2 What next for the quiz module?==&lt;br /&gt;
&lt;br /&gt;
If any other quizzy people are there, we should have a talk about where we see the quiz module going.&lt;br /&gt;
&lt;br /&gt;
I/the OU have the following priorities:&lt;br /&gt;
&lt;br /&gt;
# Make question type plugins really plug-in-able. At the moment there are some limitations:&lt;br /&gt;
#* All the lang strings are still in lang/en_utf8/quiz.php.&lt;br /&gt;
#* qtype plugins cannot easily feed CSS and Javascript into the page.&lt;br /&gt;
#* pluggable qtypes and pluggable inport/export filters don&#039;t play nicely together.&lt;br /&gt;
# Write some new question types.&lt;br /&gt;
# Make some improvements to existing question types.&lt;br /&gt;
# Get RQP working again, so our in-house question engine can talk to Moodle.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m Interested:&#039;&#039;&lt;br /&gt;
# Tim Hunt&lt;br /&gt;
&lt;br /&gt;
==Performance profiling==&lt;br /&gt;
&lt;br /&gt;
Pick a (memory|database) hog and put it on a diet. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;I&#039;m interested&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# martin langhoff&lt;br /&gt;
&lt;br /&gt;
==Add your suggestion here ...==&lt;br /&gt;
&lt;br /&gt;
Go on, you know you want to.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [http://moodlemoot.org/ http://moodlemoot.org/]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3231</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3231"/>
		<updated>2006-04-03T20:43:42Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Added &amp;#039;isinternal&amp;#039; field to prefix_auth_type table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples sources of the same type (LDAP, database, etc)&lt;br /&gt;
* Each source has its own configuration&lt;br /&gt;
* The order in which we try the sources is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source has at least the auth_user_login function (like now).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each source in the configured order.&lt;br /&gt;
* For each order, we call auth_user_login with the user credentials and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the sources returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql gurus please adjust definition ;-)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `isinternal` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;internal&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;isinternal&#039; if this auth type is internal to Moodle (1) or not(0), i.e., if it doesn&#039;t depend on any external entity to provide authentication. Tipically this is for &#039;manual&#039;, &#039;email&#039; and &#039;none&#039;.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;internal&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;internal&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;internal&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to user each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3230</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3230"/>
		<updated>2006-03-25T22:59:20Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Remove &amp;#039;interactive&amp;#039; field from this table. It doesn&amp;#039;t make sense.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples sources of the same type (LDAP, database, etc)&lt;br /&gt;
* Each source has its own configuration&lt;br /&gt;
* The order in which we try the sources is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source has at least the auth_user_login function (like now).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each source in the configured order.&lt;br /&gt;
* For each order, we call auth_user_login with the user credentials and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the sources returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql gurus please adjust definition ;-)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;internal&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;internal&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;internal&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;internal&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to user each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Future]]&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3228</id>
		<title>Multi authentication</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Multi_authentication&amp;diff=3228"/>
		<updated>2006-03-04T22:12:55Z</updated>

		<summary type="html">&lt;p&gt;Iarenaza: Initial version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Before starting to code anything about Multi Authentication support in Moodle, I would like to share what I have in mind, so others can see the flaws and everybody can spot the problems with this approach.&lt;br /&gt;
&lt;br /&gt;
There are some big questions (see below) I don&#039;t know the answer for, so if others with more knowledge of Moodle internals (specially authentication internals) than me could answer them, that would be great.&lt;br /&gt;
&lt;br /&gt;
== Some random notes about multi-auth in Moodle ==&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
* Multiple simultaneous sources for authentication&lt;br /&gt;
* Multiples sources of the same type (LDAP, database, etc)&lt;br /&gt;
* Each source has its own configuration&lt;br /&gt;
* The order in which we try the sources is configurable&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
* Each source has at least the auth_user_login function (like now).&lt;br /&gt;
* This function can return one of the following values:&lt;br /&gt;
** AUTH_OK: the user and the password are valid&lt;br /&gt;
** AUTH_DECLINED: The user or the password are not correct or unknown to this source&lt;br /&gt;
** AUTH_DENIED: This user cannot login, even if the username and password are valid&lt;br /&gt;
** AUTH_ERROR: The source found and error during user and password validation and can&#039;t say wether they are valid or not.&lt;br /&gt;
* We try each source in the configured order.&lt;br /&gt;
* For each order, we call auth_user_login with the user credentials and test the result. &lt;br /&gt;
** if the result is AUTH_DENIED, we break out of the loop and deny the user login.&lt;br /&gt;
** if the result is AUTH_OK, we break out of the loop and allow the user login.&lt;br /&gt;
** in any other case, we continue the loop.&lt;br /&gt;
* If we finish the loop, we deny the user login (all the sources returned either AUTH_DECLINED or AUTH_ERROR, so we can&#039;t let the user log in).&lt;br /&gt;
&lt;br /&gt;
=== The (proposed) database tables ===&lt;br /&gt;
&lt;br /&gt;
(MySQL syntax, Postgresql gurus please adjust definition ;-)&lt;br /&gt;
&lt;br /&gt;
==== auth_type ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_type` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `multiple` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `interactive` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `candisable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       `removable` tinyint(1) NOT NULL default &#039;0&#039;,&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different authentication types present in this&lt;br /&gt;
Moodle installation: internal, none, ldap, db, cas, etc.&lt;br /&gt;
&lt;br /&gt;
Each auth type has to autoregister in this table when it&#039;s installed,&lt;br /&gt;
specifying:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record.&lt;br /&gt;
* &#039;name&#039;: The name of the autentication type: &#039;internal&#039;, &#039;none&#039;, &#039;ldap&#039;, &#039;db&#039;, etc. There can&#039;t be duplicated values in this field.&lt;br /&gt;
* &#039;multiple&#039;: if this auth type supports multiple instances (1) or not (0).&lt;br /&gt;
* &#039;interactive&#039;: if this auth type is interactive (1) or not (0).&lt;br /&gt;
* &#039;candisable&#039;: if this auth type can be temporarily disabled (1) or not (0)&lt;br /&gt;
* &#039;removable&#039;: if this auth type can be removed from the system (1) or not (0).&lt;br /&gt;
&lt;br /&gt;
If we decide that &#039;internal&#039;, &#039;none&#039; and/or &#039;email&#039; are special&lt;br /&gt;
authentication types and are handled separately form the rest, then&lt;br /&gt;
this last field can be removed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Can &#039;internal&#039; be disabled? I&#039;m not sure&lt;br /&gt;
about this, as all the admin users can be locked out of Moodle if we&lt;br /&gt;
mistakenly disable all the auth types needed for admin users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: Should &#039;internal&#039; auth type be handled&lt;br /&gt;
separately from all this multi-auth mess? I guess there are some&lt;br /&gt;
benefits to it, but I&#039;m not sure about it. For one, it would make the&lt;br /&gt;
above question irrelevant.&lt;br /&gt;
&lt;br /&gt;
==== auth_instance ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `typeid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(20) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `description` varchar(50) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `sortorder` integer(10) NOT NULL default &#039;0&#039;&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY(`name`)       &lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores the different auth instances available for each auth&lt;br /&gt;
type. It&#039;s managed from the authentication setup page, using&lt;br /&gt;
the add/modify/delete functionality available there. We can also&lt;br /&gt;
specify the order in which we want to user each auth-instance when&lt;br /&gt;
authenticating users.&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields are:&lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key of the record. We will put this value into the &#039;auth&#039; field in prefix_user table when we correctly authenticate a user using this auth instance (to later track where to update values from, where to check for password expiration, etc.)&lt;br /&gt;
* &#039;typeid&#039;: the auth type id of this instance. It&#039;s a foreign key into the &#039;type&#039; field of auth_type table. We need this to check if there is already an instance of a given auth type, in case that auth type doesn&#039;t allow for multiple instances.&lt;br /&gt;
* &#039;name&#039;: the name of this instance. It&#039;s the text shown in the authentication setup page to refer to this instance.&lt;br /&gt;
* &#039;description&#039;: a short description text for this instance (e.g., &#039;UK Students LDAP server&#039;).&lt;br /&gt;
* &#039;sortorder&#039;: the order in which we use each auth instance when trying to authenticate users.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIG QUESTION HERE&#039;&#039;&#039;: If we use &#039;id&#039; to fill in the &#039;auth&#039; field in&lt;br /&gt;
prefix_user, then we should only use &#039;sortorder&#039; when the user has&lt;br /&gt;
that field empty (i.e., we don&#039;t know where to authenticate this user&lt;br /&gt;
so far). Otherwise we could directly authenticate with the known&lt;br /&gt;
auth-instance. But this prevents users from &amp;quot;moving&amp;quot; between&lt;br /&gt;
authentication instances (i.e, this user &amp;quot;was&amp;quot; in our UK student&#039;s&lt;br /&gt;
LDAP server, but now &amp;quot;is&amp;quot; in our US staff database server). Is this&lt;br /&gt;
good or bad?&lt;br /&gt;
&lt;br /&gt;
==== auth_instance_settings ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  CREATE TABLE `prefix_auth_instance_settings` (&lt;br /&gt;
       `id` integer(10) NOT NULL auto_increment,&lt;br /&gt;
       `instanceid` integer(10) NOT NULL default &#039;0&#039;, &lt;br /&gt;
       `name` varchar(255) NOT NULL default &#039;&#039;, &lt;br /&gt;
       `value` text NOT NULL&lt;br /&gt;
       PRIMARY_KEY(`id`),&lt;br /&gt;
       UNIQUE KEY `instancesetting` (`instanceid`,`name`)&lt;br /&gt;
  )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This table stores each auth instance configuration settings. &lt;br /&gt;
&lt;br /&gt;
* &#039;id&#039;: the primary key for the record.&lt;br /&gt;
* &#039;instanceid&#039;: foreign key into the &#039;id&#039; field of auth_instance table. &lt;br /&gt;
* &#039;name&#039;: name of the setting.&lt;br /&gt;
* &#039;value&#039;: value for that setting.&lt;br /&gt;
&lt;br /&gt;
There can&#039;t be two (or more) identical &#039;name&#039; values for the same &#039;instanceid&#039;.&lt;br /&gt;
&lt;br /&gt;
=== The questions ===&lt;br /&gt;
&lt;br /&gt;
Some additional questions before starting to code all this mess&lt;br /&gt;
&lt;br /&gt;
# If we store the &#039;prefix_auth_intance.id&#039; value in the &#039;prefix_user.auth&#039; field as suggested above, what should we do when we &#039;&#039;&#039;remove&#039;&#039;&#039; that auth instance from our system? Should we allow removal if any users are using that instance? Should we move those users to the default auth instance (internal)? Should we choose a new auth instance for those users as part of the removal? Or should we just ignore the &#039;prefix_user.auth&#039; field during login and just proceed through the whole loop and try to find which new auth instance allows the user to login (if any)?&lt;br /&gt;
# Others?&lt;/div&gt;</summary>
		<author><name>Iarenaza</name></author>
	</entry>
</feed>