<?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=Pcharsle</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=Pcharsle"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Pcharsle"/>
	<updated>2026-06-25T19:34:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45415</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45415"/>
		<updated>2014-06-20T05:40:48Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Moodle APIs used by Lightwork in Moodle 2.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The Lightwork web service ==&lt;br /&gt;
&lt;br /&gt;
These functions make up the Lightwork Moodle web service. They will use the REST protocol. Token based authentication is replacing password based authentication.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_save_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-42425&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_get_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 Returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_get_gradingform_instances&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31890&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_save_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading areas with definitions&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31861 Inserts/updates/deletes grading definitions&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_user_flags&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|assignment id&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-40548&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_set_user_flags&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|assignment id and user flags to be set&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-41738&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Old Lightwork SOAP OKtech web service functions ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web service functions described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45414</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45414"/>
		<updated>2014-06-20T05:38:50Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The Lightwork web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The Lightwork web service ==&lt;br /&gt;
&lt;br /&gt;
These functions make up the Lightwork Moodle web service. They will use the REST protocol. Token based authentication is replacing password based authentication.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_save_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-42425&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_get_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 Returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_get_gradingform_instances&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31890&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_save_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading areas with definitions&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31861 Inserts/updates/deletes grading definitions&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_user_flags&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|assignment id&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-40548&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_set_user_flags&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|assignment id and user flags to be set&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-41738&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Old Lightwork SOAP OKtech web service functions ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web service functions described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45413</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45413"/>
		<updated>2014-06-20T05:30:53Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The Lightwork web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The Lightwork web service ==&lt;br /&gt;
&lt;br /&gt;
These functions make up the Lightwork Moodle web service. They will use the REST protocol. Token based authentication is replacing password based authentication.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_get_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 Returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grading_save_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grading_external&lt;br /&gt;
|lib/classes/grading_external.php &lt;br /&gt;
|List of grading areas with definitions&lt;br /&gt;
|write&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31861 Inserts/updates/deletes grading definitions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Old Lightwork SOAP OKtech web service functions ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web service functions described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45412</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45412"/>
		<updated>2014-06-20T05:07:18Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Migration of existing SOAP OKtech web services to Moodle core web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The Lightwork web service ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The Old Lightwork SOAP OKtech web service functions ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web service functions described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45411</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45411"/>
		<updated>2014-06-20T05:04:56Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Lightwork web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The Lightwork web service ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45410</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45410"/>
		<updated>2014-06-20T05:04:20Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Moodle 2.3 assignment module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45409</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45409"/>
		<updated>2014-06-20T05:03:37Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new proposed Lightwork and marking allocation database structures */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45408</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45408"/>
		<updated>2014-06-20T05:01:55Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Design goals */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design issues ==&lt;br /&gt;
&lt;br /&gt;
* Lightwork requires the use of either the rubric or the marking guide.&lt;br /&gt;
* Lightwork requires the use of marker allocation.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45406</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45406"/>
		<updated>2014-06-20T04:48:06Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Challenges and issues */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45405</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45405"/>
		<updated>2014-06-20T02:42:16Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork (4.x.x) is under development. This will use the new assignment module and reguire no additional Moodle customisations. To allow this, the following changes have been made to the Moodle core code:&lt;br /&gt;
&lt;br /&gt;
* The Marking Guide grading method has been added (included in Moodle 2.5)&lt;br /&gt;
* Marking allocation has been added (included in Moodle 2.6)&lt;br /&gt;
* Additional web services have been added (included in Moodle 2.8 and listed later in this page)&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45404</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=45404"/>
		<updated>2014-06-20T02:32:24Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.8}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
The current version of Lightwork (3.x.x) uses the old assignment module. It interacts with Moodle using custom web services which are installed in Moodle by using the [[Local_customisation|local customisations]] hook and the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It also uses additional database tables which are installed as part of the local customisation.&lt;br /&gt;
&lt;br /&gt;
A new version of Lightwork is under development.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45403</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45403"/>
		<updated>2014-06-20T02:18:20Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_flags || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_flags for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_set_user_flags || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Sets the specified user_flags for an assignment || MDL-41738&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_mappings || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_mappings for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_revert_submissions_to_draft || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reverts the list of submissions to draft status || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_lock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Prevent students from making changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_unlock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Allow students to make changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_submission || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update the current students submission || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_submit_for_grading || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Submit the current students assignment for grading || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_grade || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a grade update for a single student. || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_grades || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.7 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save grade updates for one or more students. || MDL-42425&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_user_extensions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a list of assignment extensions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_reveal_identities || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reveal the identities for a blind marking assignment || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned. Will be deprecated and replaced by core_grading_get_definitions in 2.6|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_save_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.8 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Accepts an array of areas as a parameter. The areas contain grading definitions with criteria for inserting and updating|| MDL-31861&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45402</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45402"/>
		<updated>2014-06-20T02:13:19Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_flags || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_flags for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_mappings || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_mappings for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_revert_submissions_to_draft || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reverts the list of submissions to draft status || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_lock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Prevent students from making changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_unlock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Allow students to make changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_submission || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update the current students submission || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_submit_for_grading || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Submit the current students assignment for grading || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_grade || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a grade update for a single student. || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_grades || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.7 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save grade updates for one or more students. || MDL-42425&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_user_extensions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a list of assignment extensions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_reveal_identities || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reveal the identities for a blind marking assignment || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned. Will be deprecated and replaced by core_grading_get_definitions in 2.6|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_save_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.8 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Accepts an array of areas as a parameter. The areas contain grading definitions with criteria for inserting and updating|| MDL-31861&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45401</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=45401"/>
		<updated>2014-06-20T02:07:27Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_flags || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_flags for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_mappings || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_mappings for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_revert_submissions_to_draft || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reverts the list of submissions to draft status || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_lock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Prevent students from making changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_unlock_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Allow students to make changes to a list of submissions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_submission || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update the current students submission || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_submit_for_grading || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Submit the current students assignment for grading || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_grade || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a grade update for a single student. || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_save_user_extensions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Save a list of assignment extensions || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_reveal_identities || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Reveal the identities for a blind marking assignment || MDL-37148&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned. Will be deprecated and replaced by core_grading_get_definitions in 2.6|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_save_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.8 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Accepts an array of areas as a parameter. The areas contain grading definitions with criteria for inserting and updating|| MDL-31861&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42308</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42308"/>
		<updated>2013-09-11T02:53:38Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_flags || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_flags for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_user_mappings || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the user_mappings for assignments || MDL-40548&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned. Will be deprecated and replaced by core_grading_get_definitions in 2.6|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42307</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42307"/>
		<updated>2013-09-11T02:46:41Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31890&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42306</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=42306"/>
		<updated>2013-09-11T02:42:30Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|grading&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grading_get_gradingform_instances() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.6 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the instances and fillings for the requested definition id. An optional since parameter allows the number of records returned to be reduced so that only those with a timemodified value &amp;gt;= since are returned|| MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=38615</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=38615"/>
		<updated>2013-03-27T04:10:33Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. An optionall activeonly parameter can be provided so that only the active grading method is returned.|| MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=38614</id>
		<title>Web service API functions</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Web_service_API_functions&amp;diff=38614"/>
		<updated>2013-03-27T03:52:18Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Core web service functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle_2.0}}&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Color meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | Implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | Must be implemented&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | Suggested&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Web service protocols==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! Name !! Moodle Ver. !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | AMF || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adobe protocol to communicate with Flash/Flex apps || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning XML) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML data accessed through a REST API (not restful) || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | REST (returning JSON) || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | JSON data accessed through a REST API (not restful) || MDL-29242&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  | REST (returning JSONP) || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | Would be very useful for client-side JavaScript || MDL-29913&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdfcd;&amp;quot;  |  JSON || style=&amp;quot;background:#ffdfcd;&amp;quot;  | 2.X || style=&amp;quot;background:#ffdfcd;&amp;quot;  | JSON server receives a JSON encoded params and return JSON encoded values. || MDL-21341&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffdead;&amp;quot;  | SOAP|| style=&amp;quot;background:#ffdead;&amp;quot;  | 2.0 || style=&amp;quot;background:#ffdead;&amp;quot;  | Very important for interoperating with Java and .Net applications. There was a partial implementation JAVA/.Net in Moodle 2.0, but it does not work for anything but the most trivial functions.  It is fully working with PHP clients.|| MDL-20804, MDL-28988, MDL-28989&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | XMLRPC|| style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | XML remote-procedure call. || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Web service functions==&lt;br /&gt;
&lt;br /&gt;
=== Naming convention ===&lt;br /&gt;
&lt;br /&gt;
We updated (regularised) the naming convention in Moodle 2.2.  See MDL-29106 for those details.&lt;br /&gt;
&lt;br /&gt;
All functions should be named as follows:&lt;br /&gt;
&lt;br /&gt;
* wsfunction = fullcomponent_methodname  &lt;br /&gt;
* fullcomponent = [https://docs.moodle.org/dev/Frankenstyle frankenstyle] (eg core_xxxx or mod_xxx etc)&lt;br /&gt;
* methodname = verb_noun(s)&lt;br /&gt;
* verb = get|create|delete|update&lt;br /&gt;
* noun = moodle objects, usually plural (eg posts, discussions, users, courses etc)&lt;br /&gt;
&lt;br /&gt;
=== Core web service functions ===&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
!Area!! Moodle 2.2 name !! Moodle 2.0/2.1 name !! Introduced in !!  class=&amp;quot;unsortable&amp;quot; |Description !!  class=&amp;quot;unsortable&amp;quot; | Issue&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_create_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_delete_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete users - admin function || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_update_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update users || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get users by id || &lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  |  core_user_get_course_user_profiles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  moodle_user_get_course_participants_by_id() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get course user profiles by id || &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_create_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Create cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_update_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Update cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohorts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohorts || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_add_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Add members to cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_delete_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Delete members from cohort || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
|cohort&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_cohort_get_cohort_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  |Get cohort members || MDL-29472&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_get_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return course details ||&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_course_create_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create new courses ||&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_create_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Creates new groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  |  2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group details. || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_course_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns all groups in specified course || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groups() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes all specified groups || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_get_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_add_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_add_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Adds group members || &lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_group_members() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_group_delete_groupmembers() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Deletes group members || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_assign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_assign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role assignments || &lt;br /&gt;
|-&lt;br /&gt;
|role&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_role_unassign_roles() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_role_unassign() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual role unassignments || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | NONE || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get some minimal information about the users enrolled in a course (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
|  style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_user_get_users_by_courseid() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get enrolled users by course id || &lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_get_users_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get list of course ids that a user is enrolled in (if you are allowed to see that) ||&lt;br /&gt;
|-&lt;br /&gt;
|enrol/manual&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_enrol_manual_enrol_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Manual enrol users || &lt;br /&gt;
|-&lt;br /&gt;
|webservice&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_webservice_get_site_info() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_webservice_get_siteinfo() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some site info / user info / list web service functions || &lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_send_instant_messages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_message_send_instantmessages() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Send instant messages || &lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_notes_create_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.1 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create notes ||&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_delete_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_get_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|notes&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_notes_update_notes() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update Notes || MDL-30072&lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_get_files() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | browse moodle files || &lt;br /&gt;
|-&lt;br /&gt;
|files&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_files_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | moodle_file_upload() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.0 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | upload a file to moodle (DEPRECATED) || &lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_contents() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.2 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get course content (modules + web service file urls) || MDL-28646&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete courses || MDL-13130&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_duplicate_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | duplicate a course || MDL-32233&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_get_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_create_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_delete_categories() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete categories || MDL-32941&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_create_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | create groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_update_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | update groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_delete_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | delete groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_assign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | assign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_unassign_grouping() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | unassign groups from groupings || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|group&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_group_get_course_groupings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.3 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | get all groupings in specified course || MDL-32662&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users_by_field() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve users information for a specified unique field - If you want to do a user search, use core_user_get_users() || MDL-35543&lt;br /&gt;
|-&lt;br /&gt;
|enrol&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_enrol_get_enrolled_users_with_capability() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | For each course and capability specified, return a list of the users that are enrolled in the course and have that capability || MDL-31859&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_import_course() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Import course data from a course into another course. Does not include any user data. || MDL-32919&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_create_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Add contacts to the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_delete_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Remove contacts from the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_block_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Block contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_unblock_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Unblock contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_get_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Retrieve the contact list || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|message&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_message_search_contacts() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search for contacts || MDL-30070&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_string() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return a translated string - similar to core get_string() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_component_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return all raw strings (with {$a-&amp;gt;xxx}) for a specific component - similar to core get_component_strings() call || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|external&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_get_strings() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Return some translated strings - like several core get_string() calls || MDL-35997&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_delete_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Delete calendar events || MDL-37077&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_get_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Get calendar events || MDL-37100&lt;br /&gt;
|-&lt;br /&gt;
|calendar&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_calendar_create_calendar_events() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Create calendar events || MDL-37101&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_grades() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grades from the assignment || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_assignments() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.4 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the courses and assignments for the users capability || MDL-31873&lt;br /&gt;
|-&lt;br /&gt;
|mod_assign&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_assign_get_submissions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns the submissions for assignments || MDL-31682&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forums_by_courses || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum instances in a provided set of courses, if no courses are provided then all the forum instances the user has access to will be returned. || MDL-37247&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
|mod_forum&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | mod_forum_get_forum_discussions || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns a list of forum discussions in a provided set of forums. || MDL-30102&lt;br /&gt;
|-&lt;br /&gt;
|course&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_course_update_courses() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Update courses. || MDL-30062&lt;br /&gt;
|-&lt;br /&gt;
|user&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_user_get_users() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Search users. - If you want to get multiple users for one specific field, use core_user_get_users_by_field(), it&#039;s designed for this purpose and it should be faster. || MDL-29938&lt;br /&gt;
|-&lt;br /&gt;
|grade&lt;br /&gt;
| style=&amp;quot;background:#D4FFDF;&amp;quot;  | core_grade_get_definitions() || style=&amp;quot;background:#D4FFDF;&amp;quot;  | || style=&amp;quot;background:#D4FFDF;&amp;quot;  | 2.5 || style=&amp;quot;background:#D4FFDF;&amp;quot;  | Returns grading definitions for the course module ids and areaname provided as parameters. || MDL-31681&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
This is the list of the integrated core functions. To see the roadmap, see to the tracker issue in the section bellow.&lt;br /&gt;
&lt;br /&gt;
=== API Roadmap===&lt;br /&gt;
Tracker issue: MDL-29934&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
* [[Web services API Changes]]&lt;br /&gt;
* [[How to contribute a web service function to core]]&lt;br /&gt;
* [[Web services|Web services developer documentation]]&lt;br /&gt;
* [[:en:Web services|Web services user documentation]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Web Services]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37318</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37318"/>
		<updated>2013-01-22T01:48:05Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Lightwork web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
Currently, the Lightwork web services are installed in a Moodle installation by using the [[Local_customisation|local customisations]] hook and the web services are implemented using the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It is now proposed to add the Lightwork web services to the core Moodle 2.4 release as described in the rest of this document.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_group_members&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of group ids (required)&lt;br /&gt;
|read&lt;br /&gt;
|Returns the members of the specified groups&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37316</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37316"/>
		<updated>2013-01-22T01:45:54Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Lightwork web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
Currently, the Lightwork web services are installed in a Moodle installation by using the [[Local_customisation|local customisations]] hook and the web services are implemented using the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It is now proposed to add the Lightwork web services to the core Moodle 2.4 release as described in the rest of this document.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-34962 This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37315</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37315"/>
		<updated>2013-01-22T01:42:12Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Lightwork web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
Currently, the Lightwork web services are installed in a Moodle installation by using the [[Local_customisation|local customisations]] hook and the web services are implemented using the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It is now proposed to add the Lightwork web services to the core Moodle 2.4 release as described in the rest of this document.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_enrol_get_enrolled_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_enrol_external&lt;br /&gt;
|enrol/externallib.php &lt;br /&gt;
|List of course ids with the capabilities required, Options. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants of courses that have the specified capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_group_get_groupings&#039;&#039;&#039;&lt;br /&gt;
|core_group_external&lt;br /&gt;
|group/externallib.php&lt;br /&gt;
|List of grouping ids (required), returngroups (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-36541 Return groupings and the associated groups when returngroups is true&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37314</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=37314"/>
		<updated>2013-01-22T01:32:15Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
Currently, the Lightwork web services are installed in a Moodle installation by using the [[Local_customisation|local customisations]] hook and the web services are implemented using the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It is now proposed to add the Lightwork web services to the core Moodle 2.4 release as described in the rest of this document.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_users_get_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_course_external&lt;br /&gt;
|course/externallib.php &lt;br /&gt;
|List of course ids, Flag to specify whether all students are returned or just the ones that have submitted a submissions. List of capabilities to filter the results. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants to specified courses. This should include students and teachers. User details are returned together with capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35584</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35584"/>
		<updated>2012-09-17T00:29:40Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Description of proposed changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Description of proposed changes====&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
In MDL-32336 we have made our changes to the REST server. In the case of the other protocols we have the option to use either the same implementation or an implementation that is specific to the protocol. For instance, in the case of SOAP we could implement the file download using SOAP with attachments (http://www.w3.org/TR/SOAP-attachments). The simplest option, and our preference, is to use the same implementation for all servers.&lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35583</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35583"/>
		<updated>2012-09-16T23:40:33Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Description of proposed changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Description of proposed changes====&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
In MDL-32336 we have made our changes to the REST server. In the case of the other protocols we have the option to use either the same implementation or an implementation that is specific to the protocol. For instance, in the case of SOAP we could implement the file download using SOAP with attachments (http://www.w3.org/TR/SOAP-attachments).&lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35582</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35582"/>
		<updated>2012-09-16T23:40:00Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Description of proposed changes====&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35581</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35581"/>
		<updated>2012-09-16T23:38:00Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In MDL-32336 we have made our changes to the REST server. In the case of the other protocols we have the option to use either the same implementation or an implementation that is specific to the protocol. For instance, in the case of SOAP we could implement the file download using SOAP with attachments (http://www.w3.org/TR/SOAP-attachments).&lt;br /&gt;
&lt;br /&gt;
====Description of proposed changes====&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35533</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35533"/>
		<updated>2012-09-13T23:37:31Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Description of proposed changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
====Description of proposed changes====&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35532</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35532"/>
		<updated>2012-09-13T23:36:26Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
====Overview====&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Description of proposed changes==&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35531</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35531"/>
		<updated>2012-09-13T23:29:55Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Description of proposed changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Description of proposed changes==&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;assignid&#039; =&amp;gt; new external_value(PARAM_INT, &#039;id of assignment for which submission files will be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles($assignid) {&lt;br /&gt;
&lt;br /&gt;
        // perform application logic, get files and package them in zipfilename&lt;br /&gt;
        &lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $zipfilename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/somepath&#039; . $zipfilename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function getsubmissionfiles_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35530</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35530"/>
		<updated>2012-09-13T23:20:33Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Description of proposed changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Description of proposed changes==&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet shows the new proposed class &#039;&#039;&#039;external_file&#039;&#039;&#039; that is added to lib/externallib.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet describes a simple web service function which downloads a file using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class mod_assign_get_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35529</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35529"/>
		<updated>2012-09-13T23:11:30Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Integrate file download into the Moodle web services framework */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Description of proposed changes==&lt;br /&gt;
&lt;br /&gt;
We have created modifications to the Moodle web services by adding a new external type called external_file to allow direct file download. Our changes can be accessed from http://tracker.moodle.org/browse/MDL-32336. Our changes modify the web services servers and complement the existing web services so that the list of return data types available to developers will be:&lt;br /&gt;
&lt;br /&gt;
# external_value&lt;br /&gt;
# external_single_structure&lt;br /&gt;
# external_multiple_structure&lt;br /&gt;
# &#039;&#039;&#039;external_file&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
The following code snippet describes how the new proposed external_file could be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35528</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35528"/>
		<updated>2012-09-13T22:07:22Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Integrate file download into the Moodle web services framework */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like &#039;&#039;&#039;mod_assign_movesubmissionfilestoalocationfordownloading(assignid)&#039;&#039;&#039;&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
This 2 step process is cumbersome for clients who want a web service to consist solely of web service functions without the need to call additional php code (webservices/pluginfile.php) outside of the framework.&lt;br /&gt;
&lt;br /&gt;
The changes that we propose will allow the above 2 step process to be replaced by a single web service function call that efficiently returns a file (i.e. NOT encoding in the XML but using http streaming like pluginfile.php). So, the 2 step process described above would be replaced by a single web service function:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;mod_assign_getsubmissionfiles(assignid)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Adding new external type to allow direct file download web service&lt;br /&gt;
As proposed in http://tracker.moodle.org/browse/MDL-32336 to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35527</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35527"/>
		<updated>2012-09-13T21:41:01Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Integrate file download into the Moodle web services framework */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading, named something like mod_assign_movesubmissionfilestoalocationfordownloading()&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Adding new external type to allow direct file download web service&lt;br /&gt;
As proposed in http://tracker.moodle.org/browse/MDL-32336 to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35526</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35526"/>
		<updated>2012-09-13T21:37:55Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Integrate file download into the Moodle web services framework===&lt;br /&gt;
&lt;br /&gt;
Currently (Moodle 2.3) web service client developers cannot download files without having to create extra code outside of the web services framework. For example, in order to develop a web service function that downloads student submission files for an assignment they have to:&lt;br /&gt;
&lt;br /&gt;
# Create a web service function that performs the business logic and puts the files in a location for downloading&lt;br /&gt;
# Download the file using webservices/pluginfile.php&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Adding new external type to allow direct file download web service&lt;br /&gt;
As proposed in http://tracker.moodle.org/browse/MDL-32336 to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35525</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35525"/>
		<updated>2012-09-13T21:22:46Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in http://tracker.moodle.org/browse/MDL-32336 to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35524</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35524"/>
		<updated>2012-09-13T21:17:18Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in [http://tracker.moodle.org/browse/MDL-32336 MDL-32336] to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35523</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35523"/>
		<updated>2012-09-13T21:16:34Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in [http://tracker.moodle.org/browse/MDL-32336] to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35522</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35522"/>
		<updated>2012-09-13T21:15:09Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in &amp;quot;MDL-32336&amp;quot;:http://www.example.com link title]http://tracker.moodle.org/browse/MDL-32336 to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35521</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35521"/>
		<updated>2012-09-13T21:13:38Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in [[http://tracker.moodle.org/browse/MDL-32336|MDL-32336]] to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35520</id>
		<title>Talk:External services description</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:External_services_description&amp;diff=35520"/>
		<updated>2012-09-13T21:13:06Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Adding new external type to allow direct file download web service */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== About the different alternatives describing the available WS, by Eloy ===&lt;br /&gt;
&lt;br /&gt;
Hi, after reading the different alternatives, I&#039;m inclined to implement something like the 3rd one. Having our custom structures to define the interface to the available web services seems really better than using &amp;quot;free-form&amp;quot; structures like &amp;quot;raw&amp;quot; arrays and objects or using harcoded keywords like &amp;quot;multiple&amp;quot; and so on. It has various advantages and doesn&#039;t hurt simplicity when defining the parameters:&lt;br /&gt;
* Better PHP structures &amp;lt;--&amp;gt; XML mapping&lt;br /&gt;
* Extensibility:&lt;br /&gt;
** custom/reusable validation methods.&lt;br /&gt;
** built-in XML writing&lt;br /&gt;
** enforce some sort of common response functionality (see my concerns about returned content below).&lt;br /&gt;
&lt;br /&gt;
Anyway, I&#039;ve some (small) concerns about the example code used in the 3rd alternative, so I&#039;m writing here how it should look like ideally IMO (rationale about changes is after the code):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class moodle_group_external extends external_api {&lt;br /&gt;
    public static function add_member_parameters() {&lt;br /&gt;
        return new external_single_structure(&lt;br /&gt;
            &#039;member&#039;, array(&lt;br /&gt;
                new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                new external_param(&#039;userid&#039;, PARAM_INT, &#039;some user id&#039;)&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member($groupid, $userid) {&lt;br /&gt;
        $params = self::validate_prameters(self::add_member_parameters(), array(&#039;groupid&#039;=&amp;gt;$groupid, &#039;userid&#039;=&amp;gt;$userid));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // add_member() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_member_returns() { // Some concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function add_members_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;membership&#039;, self::add_member_parameters()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members(array $membership) {&lt;br /&gt;
        foreach($membership as $one) { // simply one iterator over the &amp;quot;single&amp;quot; function if possible&lt;br /&gt;
            self::add_member($one-&amp;gt;groupid, $one-&amp;gt;userid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function add_members_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return null;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    public static function get_groups_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;groupid&#039;, PARAM_INT, &#039;some group id&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups(array $groups) {&lt;br /&gt;
        $params = self::validate_prameters(self::get_groups_parameters(), array(&#039;groups&#039;=&amp;gt;$groups));&lt;br /&gt;
&lt;br /&gt;
        // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
        // throwing exceptions if neeeded and and calling low level (grouplib)&lt;br /&gt;
        // get_groups() function that will be one in charge of the functionality without&lt;br /&gt;
        // further checks.&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    public static function get_groups_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;groups&#039;, new external_single_structure(&lt;br /&gt;
                &#039;group&#039;, array(&lt;br /&gt;
                    new external_param(&#039;id&#039;, PARAM_INT, &#039;some group id&#039;),&lt;br /&gt;
                    new external_param(&#039;name&#039;, PARAM_TEXT, &#039;multilang compatible name, course unique&#039;),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_RAW, &#039;just some text&#039;),&lt;br /&gt;
                    new external_param(&#039;enrolmentkey&#039;, PARAM_RAW, &#039;group enrol secret phrase&#039;)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class moodle_user_external extends external_api {&lt;br /&gt;
    public static function create_users_parameters() {&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
                    new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
                    new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
                    new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
                    new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
                    new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
                    new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
                    new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
                    new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
                    new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
                    new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
                    new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;preference&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User preferences&#039;, false),&lt;br /&gt;
                    new external_multiple_structure(&lt;br /&gt;
                        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
                            &#039;customfield&#039;, array(&lt;br /&gt;
                                new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
                                new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
                            )&lt;br /&gt;
                        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users(array $users) {&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array(&#039;users&#039;=&amp;gt;$users));&lt;br /&gt;
&lt;br /&gt;
        foreach ($users as $user) {&lt;br /&gt;
            // all the parameter/behavioural checks and security constrainsts go here,&lt;br /&gt;
            // throwing exceptions if neeeded and and calling low level (userlib)&lt;br /&gt;
            // add_user() function that will be one in charge of the functionality without&lt;br /&gt;
            // further checks.&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    public static function create_users_returns() { // BIG concerns here. See below.&lt;br /&gt;
        return new external_multiple_structure(&lt;br /&gt;
            &#039;users&#039;, new external_single_structure(&lt;br /&gt;
                &#039;user&#039;, array(&lt;br /&gt;
                    new external_param(&#039;userid&#039;, PARAM_INT, &#039;id of the created user&#039;))&lt;br /&gt;
            )&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Changes from original code are:====&lt;br /&gt;
&lt;br /&gt;
* Small change in structure names. &#039;&#039;external_bulk_array&#039;&#039; renamed to &#039;&#039;external_multiple_structure&#039;&#039; and &#039;&#039;external_assoc_array&#039;&#039; to &#039;&#039;external_single_structure&#039;&#039; (note that &#039;&#039;structure&#039;&#039; can be changed to anything else). The important bits are the &#039;&#039;single/multiple&#039;&#039; ones vs. the &#039;&#039;assoc/bulk&#039;&#039;. Clear IMO.&lt;br /&gt;
* Moved the &amp;quot;name&amp;quot; of the single structure and param classes to the constructor (no need for associative arrays). Clear syntax.&lt;br /&gt;
* Small change in &#039;&#039;external_multiple_structure&#039;&#039; to add the missing &amp;quot;name&amp;quot; to its constructor. Matching previous point.&lt;br /&gt;
* The xxxx_parameters() function will return directly one &#039;&#039;single&#039;&#039; or &#039;&#039;multiple&#039;&#039; structure, saving one nesting level from original code.&lt;br /&gt;
* Reuse as much as possible:&lt;br /&gt;
** The &#039;&#039;moodle_group_external&#039;&#039; is a clear example. Once we have the &#039;&#039;single&#039;&#039; service implemented (add_member), it&#039;s pretty easy to build its &#039;&#039;multiple&#039;&#039; alternative. Just reuse the single parameters definition and the single &#039;&#039;executor&#039;&#039;. IMO we should &#039;&#039;&#039;always&#039;&#039;&#039; enforce the single/multiple duality.&lt;br /&gt;
** Also, although there isn&#039;t an example, I think we could have some &amp;quot;habitual&amp;quot; structures predefined somewhere, see for example, the &#039;&#039;preference&#039;&#039; or the &#039;&#039;customfield&#039;&#039; single structures (or the whole &#039;&#039;preferences&#039;&#039; or &#039;&#039;customfields&#039;&#039; multiple ones if you prefer). They are basically the same (name/value pairs). It could be useful to have one predefined &amp;quot;name_value&amp;quot; structure somewhere and use it where necessary (user preferences, user custom fields, various config options...).&lt;br /&gt;
&lt;br /&gt;
====Concerns about return functions:====&lt;br /&gt;
&lt;br /&gt;
In the example above we have a good example. There are some xxxx_return() functions returning NULLs, others returning multiple structures (and also is possible to return single structures or numbers or whatever).&lt;br /&gt;
&lt;br /&gt;
IMO returned structures should be, always, encapsulated into something constant, call it &#039;external_response&#039;. Then, within that, we can return some &#039;&#039;&#039;constant information&#039;&#039;&#039; (bool result, string error, whatever...) and some &#039;&#039;&#039;dynamic information&#039;&#039;&#039; (single/multiple structures).&lt;br /&gt;
&lt;br /&gt;
Also, while it&#039;s really simple to return results for single structures (for example the &#039;&#039;add_member()&#039;&#039; above will return one simple result ), it&#039;s more complex to do so for multiple structures. For example, the &#039;&#039;add_members()&#039;&#039; above must return one different result for each groupid-userid added. Imagine you create one client sending 4 pairs (within a multiple structure well formed WS request). &lt;br /&gt;
&lt;br /&gt;
And &#039;&#039;&#039;only one of them is added successfully&#039;&#039;&#039;, other fails because the userid is incorrect, another fails because it already exists and the 4th fails because the user cannot handle that group, or because the user isn&#039;t enrolled in the course the group belongs to or... whatever. How will the &#039;&#039;&#039;return information be formatted&#039;&#039;&#039; to inform about all those heterogeneous situations? How will the client know the exact status of each pair sent in the multiple request? &lt;br /&gt;
&lt;br /&gt;
Should we introduce one mandatory &amp;quot;key&amp;quot; parameter in all the occurrences within one multiple request, in order to get the response properly identified by those keys? Or will the multiple request be rejected as a whole (I think this isn&#039;t possible). &lt;br /&gt;
&lt;br /&gt;
Note I don&#039;t know if that has been resolved in other places of the WS documentation but I haven&#039;t been able to find it, hence the warn. ;-)&lt;br /&gt;
&lt;br /&gt;
So, summarising, &#039;&#039;&#039;I like the 3rd alternative&#039;&#039;&#039; with the changes specified above (in order to make it more readable/simple, basically). And I think the &amp;quot;response&amp;quot; (return) part is &#039;&#039;&#039;at least as important as&#039;&#039;&#039; the &amp;quot;request&amp;quot; (parameters) part, and it still needs more work/definition/polishing. Shouldn&#039;t be difficult to achieve that.&lt;br /&gt;
&lt;br /&gt;
Hope this helps, ciao --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 00:24, 18 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
Offtopic: I hate the &amp;quot;external&amp;quot; keyword everywhere. :-D :-P&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The second revision to this alternative (adding new &amp;quot;name&amp;quot; parameter to all the classes vs old associative arrays) has been discussed/agreed with Petr. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 20:39, 19 September 2009 (UTC)&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I think the flexible return values are problematic - I personally prefer exception when anything goes wrong, getting complex result requires extra post processing of results. So my -1 here. [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]]&lt;br /&gt;
:But &amp;quot;client&amp;quot; must know what has been processed and what not. What if something breaks in the 4th element of a multiple request? How is the client informed about the 3 first elements already being processed and the rest not? [[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 09:10, 18 September 2009 (UTC)&lt;br /&gt;
::Right, the methods working with bulk data should do that, I am just not sure single methods should return complex structures, also we could send this extra information through exception - the bulk methods should call simple ones and could return exception containing the original exception + progress info [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 20:32, 19 September 2009 (UTC)&lt;br /&gt;
::: I agree with that (the bulk function will catch exception of the single function, and keep going to process the rest) [[User:Jerome Mouneyrac (jmouneyrac)|Jerome Mouneyrac (jmouneyrac)]] 12:23, 21 September 2009 (Perth)&lt;br /&gt;
::: Agree too, that is part of code reusability (throwing exception with useful info in single/multiple methods and catching it at higher level to provide WS response. Anyway my concerns are about to have a well-defined response, able to support responses both to single and multiple requests. Right now, it&#039;s undefined. --[[User:Eloy Lafuente (stronk7)|Eloy Lafuente (stronk7)]] 07:51, 21 September 2009 (UTC)&lt;br /&gt;
:::: the parameter syntax allows us to describe both simple and complex return types, for any kind of problems we would use exceptions - in fact we could define add 3rd description function which describes some basic exceptions - I do not like the idea of using normal return when something goes wrong&lt;br /&gt;
&lt;br /&gt;
====Validate_parameters requires that we define a way to match parameters with the description====&lt;br /&gt;
&lt;br /&gt;
Edit: I consider that external functions are normal php functions. So they can accept anything as parameters (very complex param like array of object containing array of object), and they can have several parameters.&lt;br /&gt;
&lt;br /&gt;
I&#039;m writing the validate_parameters function. There is a thing we didn&#039;t define into the description specs.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to validate parameters, we need to be able to match the parameters to the description&amp;lt;br/&amp;gt;&lt;br /&gt;
I guess we&#039;ll match the parameters like that :&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;description =&amp;gt; parameter type&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
external_multiple_structure =&amp;gt; a non associative array&amp;lt;br/&amp;gt;&lt;br /&gt;
external_single_structure =&amp;gt; an object&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Moreover I think funtion_name_parameters() should return a array of external_xxxx_structure. So we can support functions with more than one parameter like function_name($param1, $param2, $param3).&amp;lt;br/&amp;gt; The validation call will be $params = self::validate_prameters(self::function_name_description(), array($param1, $param2, $param3)); &lt;br /&gt;
&lt;br /&gt;
:oh no - we can use multiple params of PHP function, the mapping is simple, you just need to solve the order of params in PHP to names in description - my proposal was solving exactly that [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 15:37, 24 September 2009 (UTC)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
///example for a function with one param only&lt;br /&gt;
&lt;br /&gt;
  public static function create_users_parameters() {&lt;br /&gt;
        return array (&lt;br /&gt;
            new external_multiple_structure(&lt;br /&gt;
        &#039;users&#039;, new external_single_structure(&lt;br /&gt;
        &#039;user&#039;, array(&lt;br /&gt;
        new external_param(&#039;username&#039;, PARAM_USERNAME, &#039;Username policy is defined in Moodle security config&#039;),&lt;br /&gt;
        new external_param(&#039;password&#039;, PARAM_RAW, &#039;Moodle passwords can consist of any character&#039;),&lt;br /&gt;
        new external_param(&#039;firstname&#039;, PARAM_NOTAGS, &#039;The first name(s) of the user&#039;),&lt;br /&gt;
        new external_param(&#039;lastname&#039;, PARAM_NOTAGS, &#039;The family name of the user&#039;),&lt;br /&gt;
        new external_param(&#039;email&#039;, PARAM_EMAIL, &#039;A valid and unique email address&#039;),&lt;br /&gt;
        new external_param(&#039;auth&#039;, PARAM_AUTH, &#039;Auth plugins include manual, ldap, imap, etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;confirmed&#039;, PARAM_NUMBER, &#039;Active user: 1 if confirmed, 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;idnumber&#039;, PARAM_RAW, &#039;An arbitrary ID code number perhaps from the institution&#039;, false),&lt;br /&gt;
        new external_param(&#039;emailstop&#039;, PARAM_NUMBER, &#039;Email is blocked: 1 is blocked and 0 otherwise&#039;, false),&lt;br /&gt;
        new external_param(&#039;lang&#039;, PARAM_LANG, &#039;Language code such as &amp;quot;en_utf8&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;theme&#039;, PARAM_THEME, &#039;Theme name such as &amp;quot;standard&amp;quot;, must exist on server&#039;, false),&lt;br /&gt;
        new external_param(&#039;timezone&#039;, PARAM_ALPHANUMEXT, &#039;Timezone code such as Australia/Perth, or 99 for default&#039;, false),&lt;br /&gt;
        new external_param(&#039;mailformat&#039;, PARAM_INTEGER, &#039;Mail format code is 0 for plain text, 1 for HTML etc&#039;, false),&lt;br /&gt;
        new external_param(&#039;description&#039;, PARAM_TEXT, &#039;User profile description, as HTML&#039;, false),&lt;br /&gt;
        new external_param(&#039;city&#039;, PARAM_NOTAGS, &#039;Home city of the user&#039;, false),&lt;br /&gt;
        new external_param(&#039;country&#039;, PARAM_ALPHA, &#039;Home country code of the user, such as AU or CZ&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;preferences&#039;, new external_single_structure(&lt;br /&gt;
        &#039;preference&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the preference&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the preference&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User preferences&#039;, false),&lt;br /&gt;
        new external_multiple_structure(&lt;br /&gt;
        &#039;customfields&#039;, new external_single_structure(&lt;br /&gt;
        &#039;customfield&#039;, array(&lt;br /&gt;
        new external_param(&#039;type&#039;, PARAM_ALPHANUMEXT, &#039;The name of the custom field&#039;),&lt;br /&gt;
        new external_param(&#039;value&#039;, PARAM_RAW, &#039;The value of the custom field&#039;)&lt;br /&gt;
        )&lt;br /&gt;
        ), &#039;User custom fields&#039;, false)&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        )&lt;br /&gt;
        ///if the function had a second param we would add it here&lt;br /&gt;
        /// , new external_multiple_structure(...)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
 public static function create_users(array $users) {&lt;br /&gt;
        ...&lt;br /&gt;
        $params = self::validate_prameters(self::create_users_parameters(), array($users));&lt;br /&gt;
/// if the function had a second param we would have wrote&lt;br /&gt;
/// public static function create_users(array $users, array $second_param) {&lt;br /&gt;
///     $params = self::validate_prameters(self::create_users_parameters(), array($users, $second_param));&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Adding new external type to allow direct file download web service===&lt;br /&gt;
&lt;br /&gt;
As proposed in [http://tracker.moodle.org/browse/MDL-32336|MDL-32336] to add a new type called external_file to allow direct file download web service.&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection under &#039;&#039;base description classes&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * File description class. Which indicates the response will return a file for download.&lt;br /&gt;
 * Implementation that is using external_file is expected to return an associative-array/hashmap&lt;br /&gt;
 * which contains the file to be downloaded.&lt;br /&gt;
 * &lt;br /&gt;
 * The file download process is handled using send_file() and send_temp_file() from lib/filelib.php.&lt;br /&gt;
 * The properties of the associative-array/hashmap expected are:&lt;br /&gt;
 * - filename  - string - proposed file name when saving file&lt;br /&gt;
 * - path      - string - path to file, preferably from moodledata/temp/something; or content of file itself&lt;br /&gt;
 * - tempfile  - boolean - will use send_temp_file() if true, otherwise use send_file()&lt;br /&gt;
 */&lt;br /&gt;
class external_file extends external_description {&lt;br /&gt;
    public function __construct($desc=&#039;&#039;, $required=VALUE_REQUIRED, $default=null) {&lt;br /&gt;
        parent::__construct($desc, $required, $default);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following snippet is proposed to be added to the wiki page&#039;s &#039;&#039;&#039;externallib.php&#039;&#039;&#039; subsection after &#039;&#039;Externallib.php example&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;external_file examples:&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
This example shows how to develop web service function which send file for download using external_file type.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class local_wsfile_external extends external_api {&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_parameters() {&lt;br /&gt;
        return new external_function_parameters(&lt;br /&gt;
                array(&#039;filename&#039; =&amp;gt; new external_value(PARAM_TEXT, &#039;name of file to be downloaded&#039;)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file($filename) {&lt;br /&gt;
        $result = array();&lt;br /&gt;
        $result[&#039;filename&#039;] = $filename;&lt;br /&gt;
        $result[&#039;path&#039;] = &#039;/moodle/moodledata&#039; . $filename;&lt;br /&gt;
        $result[&#039;tempfile&#039;] = true;&lt;br /&gt;
        &lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public static function download_file_returns() {&lt;br /&gt;
        return new external_file();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35017</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35017"/>
		<updated>2012-08-22T05:50:24Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Support the marking process */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations, modes, tutorial groups, or other criteria). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
GW - my concern with the paragraph above is that it implies that the processes of allocating manually, randomly or by groups will all operate identically. It is my understanding that the spec below is suggesting that manual allocation happens within the assignment grading table, whereas random allocation will effectively occur via the use of groups and will take advantage of the random allocation mechanisms already built into the group manager in Moodle. Likewise allocating by groups will take advantage of the same existing Moodle functionality. It was my impression that changing allocations during the marking process if groups (including random groups) are used, will require changes to the group membership. This may be a minor point, but I think it is worth highlighting.&lt;br /&gt;
&lt;br /&gt;
EH - Grette, putting implementation issues aside, do you agree with the functionality proposed and importantly, with the fundamental difference to what I have called &#039;distribution of marking&#039;? If we can agree on the fundamentals first we can then see how the implementation will work. What is currently described below (e.g., with the screenshots) suffers, in my opinion, from confusion about what we want to achieve.&lt;br /&gt;
&lt;br /&gt;
GW - I guess I am finding it difficult to see what the difference between allocation and distribution is in reference to identifying which marker will mark which students work. I am unsure what the implications of highlighting the difference will be. &lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
GW - EAM are also interested in manual allocation of marking as an addition to using groups.&lt;br /&gt;
&lt;br /&gt;
EH: Are you talking about manual distribution of subsets of students to individual markers/several markers (with processes like I have described in the first point about &#039;Distribution&#039;, or, are you talking about supporting the marking process?&lt;br /&gt;
GW - see my comment above about not being clear on the reason for the distinction between allocation and distribution.&lt;br /&gt;
&lt;br /&gt;
PC: I believe a simplified set of statuses would be good when there is only a single marker:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
GW - my sense is that using the hide/show controls for the gradebook entry requires teachers to move to a different part of Moodle in order to ensure that students do not receive their grades/feedback immediately. A function that sits within the assignment module itself will be more visible and hopefully therefore more usable. We should definitely not build something however that prevents teachers from using the &#039;hide/show gradebook entry&#039; method.&lt;br /&gt;
&lt;br /&gt;
EH: I think that the additional functionality would be well placed. Hiding marking from students needs to occur in two places: in the gradebook and in the assignment activity. Hiding the gragebook entry is fairly easy for the teacher (but, as Grette points out, it is in a different place in Moodle). Hiding the assignment activity has unwelcome side effects. As I understand it, the teacher needs to hide the assignment from student view so students cannot see marks and feedback. But, for example, this means that students cannot make late submissions (as they cannot see the assignment ...).&lt;br /&gt;
&lt;br /&gt;
PC: Just to be clear, what I was talking about was using the proposed release control in the assignment settings to hide the grade book entries (not expecting teachers to move to a different part of Moodle). In other words, when an assignment is created with release control, it would be automatically set to &#039;hidden&#039; in the grade book.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
GW - this would be highly problematic for groups that get their membership from Student Information Systems.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Answer from our last meeting : marker allocation tables will be used&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PC: I believe the following statuses would be good:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
PC - I don&#039;t agree with skipping the &amp;quot;Ready for Release&amp;quot; status since it is an important part of the review process. However, it is possible to make the switching between statuses fast and efficient by having bulk options such as &amp;quot;Release all&amp;quot; that automatically selects marking with one status and moves it to the next.&lt;br /&gt;
&lt;br /&gt;
Where it would be appropriate to reduce the number of statuses (but possibly not in our first Moodle 2.4 release) is when there is only a &lt;br /&gt;
single marker. So, I think we need the following:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35016</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35016"/>
		<updated>2012-08-22T05:33:02Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Control the release of marking to students */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations, modes, tutorial groups, or other criteria). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
GW - my concern with the paragraph above is that it implies that the processes of allocating manually, randomly or by groups will all operate identically. It is my understanding that the spec below is suggesting that manual allocation happens within the assignment grading table, whereas random allocation will effectively occur via the use of groups and will take advantage of the random allocation mechanisms already built into the group manager in Moodle. Likewise allocating by groups will take advantage of the same existing Moodle functionality. It was my impression that changing allocations during the marking process if groups (including random groups) are used, will require changes to the group membership. This may be a minor point, but I think it is worth highlighting.&lt;br /&gt;
&lt;br /&gt;
EH - Grette, putting implementation issues aside, do you agree with the functionality proposed and importantly, with the fundamental difference to what I have called &#039;distribution of marking&#039;? If we can agree on the fundamentals first we can then see how the implementation will work. What is currently described below (e.g., with the screenshots) suffers, in my opinion, from confusion about what we want to achieve.&lt;br /&gt;
&lt;br /&gt;
GW - I guess I am finding it difficult to see what the difference between allocation and distribution is in reference to identifying which marker will mark which students work. I am unsure what the implications of highlighting the difference will be. &lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
GW - EAM are also interested in manual allocation of marking as an addition to using groups.&lt;br /&gt;
&lt;br /&gt;
EH: Are you talking about manual distribution of subsets of students to individual markers/several markers (with processes like I have described in the first point about &#039;Distribution&#039;, or, are you talking about supporting the marking process?&lt;br /&gt;
GW - see my comment above about not being clear on the reason for the distinction between allocation and distribution.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
GW - my sense is that using the hide/show controls for the gradebook entry requires teachers to move to a different part of Moodle in order to ensure that students do not receive their grades/feedback immediately. A function that sits within the assignment module itself will be more visible and hopefully therefore more usable. We should definitely not build something however that prevents teachers from using the &#039;hide/show gradebook entry&#039; method.&lt;br /&gt;
&lt;br /&gt;
EH: I think that the additional functionality would be well placed. Hiding marking from students needs to occur in two places: in the gradebook and in the assignment activity. Hiding the gragebook entry is fairly easy for the teacher (but, as Grette points out, it is in a different place in Moodle). Hiding the assignment activity has unwelcome side effects. As I understand it, the teacher needs to hide the assignment from student view so students cannot see marks and feedback. But, for example, this means that students cannot make late submissions (as they cannot see the assignment ...).&lt;br /&gt;
&lt;br /&gt;
PC: Just to be clear, what I was talking about was using the proposed release control in the assignment settings to hide the grade book entries (not expecting teachers to move to a different part of Moodle). In other words, when an assignment is created with release control, it would be automatically set to &#039;hidden&#039; in the grade book.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
GW - this would be highly problematic for groups that get their membership from Student Information Systems.&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Answer from our last meeting : marker allocation tables will be used&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PC: I believe the following statuses would be good:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
PC - I don&#039;t agree with skipping the &amp;quot;Ready for Release&amp;quot; status since it is an important part of the review process. However, it is possible to make the switching between statuses fast and efficient by having bulk options such as &amp;quot;Release all&amp;quot; that automatically selects marking with one status and moves it to the next.&lt;br /&gt;
&lt;br /&gt;
Where it would be appropriate to reduce the number of statuses (but possibly not in our first Moodle 2.4 release) is when there is only a &lt;br /&gt;
single marker. So, I think we need the following:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35006</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35006"/>
		<updated>2012-08-21T23:27:00Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations or modes). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Answer from our last meeting : marker allocation tables will be used&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PC: I believe the following statuses would be good:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
PC - I don&#039;t agree with skipping the &amp;quot;Ready for Release&amp;quot; status since it is an important part of the review process. However, it is possible to make the switching between statuses fast and efficient by having bulk options such as &amp;quot;Release all&amp;quot; that automatically selects marking with one status and moves it to the next.&lt;br /&gt;
&lt;br /&gt;
Where it would be appropriate to reduce the number of statuses (but possibly not in our first Moodle 2.4 release) is when there is only a &lt;br /&gt;
single marker. So, I think we need the following:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35005</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35005"/>
		<updated>2012-08-21T23:16:02Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Marker allocations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations or modes). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Answer from our last meeting : marker allocation tables will be used&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
PC - I don&#039;t agree with skipping the &amp;quot;Ready for Release&amp;quot; status since it is an important part of the review process. However, it is possible to make the switching between statuses fast and efficient by having bulk options such as &amp;quot;Release all&amp;quot; that automatically selects marking with one status and moves it to the next.&lt;br /&gt;
&lt;br /&gt;
Where it would be appropriate to reduce the number of statuses (but possibly not in our first Moodle 2.4 release) is when there is only a &lt;br /&gt;
single marker. So, I think we need the following:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35004</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35004"/>
		<updated>2012-08-21T23:13:49Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* A teacher has assistants helping them mark and wants to review all marks before they are released 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations or modes). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Will you be creating new groups to hold the allocations?&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
PC - I don&#039;t agree with skipping the &amp;quot;Ready for Release&amp;quot; status since it is an important part of the review process. However, it is possible to make the switching between statuses fast and efficient by having bulk options such as &amp;quot;Release all&amp;quot; that automatically selects marking with one status and moves it to the next.&lt;br /&gt;
&lt;br /&gt;
Where it would be appropriate to reduce the number of statuses (but possibly not in our first Moodle 2.4 release) is when there is only a &lt;br /&gt;
single marker. So, I think we need the following:&lt;br /&gt;
&lt;br /&gt;
Multiple markers - &amp;quot;Allocated&amp;quot;-&amp;gt;&amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;Marking Completed&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Ready for Release&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Single marker - &amp;quot;In Marking&amp;quot;-&amp;gt;&amp;quot;In Review&amp;quot;-&amp;gt;&amp;quot;Released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35002</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35002"/>
		<updated>2012-08-21T22:18:38Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Settings added to the mod_assign settings page */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations or modes). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
PC - My concern is that being able to choose a combination of settings in this way does not make it clear to the teacher what they will end up with at the end. For instance, a teacher who wants to take advantage of the advanced marking process should not have to work out that they have to select &amp;quot;Release grades immediately - No&amp;quot; in order to do this. Also, see my comment earlier about the use of the &amp;quot;hiding&amp;quot; facility in the grade book to control the release.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Will you be creating new groups to hold the allocations?&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35001</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=35001"/>
		<updated>2012-08-21T21:25:34Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Control the release of marking to students */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals, rationale and fundamentals =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Control the distribution&lt;br /&gt;
* Support the marking process&lt;br /&gt;
* Control the release of marking to students&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Control the distribution ==&lt;br /&gt;
&lt;br /&gt;
This is relevant in the context of large courses where groups/groupings are used to divide the students into groups and to associate dedicated staff with these groups. In terms of assignment marking the idea is that staff associated with groups are responsible for the marking of students in their groups and fulfil such marking independently from the marking of other groups. &lt;br /&gt;
&lt;br /&gt;
An example would be: A course with 300 students is divided into 3 groups of students (based on different delivery locations or modes). Two or more staff are associated with each group (one teacher and several teaching assistants). The same assignment is setup for the whole course. The staff associated with each group of students are responsible for marking their groups. &lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) staff associated with a group should only see the students belonging to this group. It is not recorded which staff member is marking which students. &lt;br /&gt;
The staff member in charge of the overall course might have a setting, which allows to see assignment marking for all students (of all groups).&lt;br /&gt;
&lt;br /&gt;
This functionality is primarily of interest to the EAM project.&lt;br /&gt;
&lt;br /&gt;
== Support the marking process ==&lt;br /&gt;
&lt;br /&gt;
The focus here is on assisting with the marking process, typically in situations where multiple teachers and/or teaching assistants form a marking team. The idea is to allow each individual marker to have an overview of marking assigned to them and of the status this marking is in. The teacher in charge of the assignment wants to be able to see how marking is progressing and what quality the marking is (per marker and across markers). &lt;br /&gt;
&lt;br /&gt;
To achieve this focus two aspects need to be introduced:&lt;br /&gt;
* Marker allocations;&lt;br /&gt;
* Marking statuses.&lt;br /&gt;
&lt;br /&gt;
With marker allocations, it is recorded which marker (teacher or teaching assistant) is marking which student. Only the marker allocated can mark a student. The teacher in charge of the assignment decides the marker allocation (the teacher selects all staff involved in marking and then distributes marking manually, randomly, or even based on groups). As the marking progresses, allocations can be changed (e.g., when a marker becomes unavailable).&lt;br /&gt;
&lt;br /&gt;
The following marking statuses are suggested:&lt;br /&gt;
* Allocated (the marker has not yet started)&lt;br /&gt;
* In marking (the marker has started but not yet finished)&lt;br /&gt;
* Marking completed (the marker has finished but might need to go back for checking/corrections)&lt;br /&gt;
* In review (the marking is now with the teacher in charge for quality checking)&lt;br /&gt;
* Ready for release (the teacher in charge is satisfied with the marking but wait before giving students access to the marking)&lt;br /&gt;
* Released (students have access to the marking.&lt;br /&gt;
&lt;br /&gt;
The marking statuses are for use by staff. The marking statuses are not visible to students.&lt;br /&gt;
The default setting will be that students can see who has marked them (but this can be changed).&lt;br /&gt;
Marking can be taken from one status to the next on individual student basis, yet there are also bulk transitions (e.g., to release of ‘ready’ marking). Marking can be taken back into a previous status (e.g., from in review back to in marking if more work is required).&lt;br /&gt;
&lt;br /&gt;
When looking at the assignment marking (mod/assign/view.php?id=3&amp;amp;action=grading) it is displayed who is marking which student (and only the staff assigned can edit the marking).&lt;br /&gt;
&lt;br /&gt;
The functionality related to the marking process has its origins in Lightwork and is primarily of interest to the Lightwork online project.&lt;br /&gt;
&lt;br /&gt;
== Control the release of marking to students ==&lt;br /&gt;
&lt;br /&gt;
A problem with the current Moodle assignment module (2.3) is that students can immediately see their marking results (if the teacher does not take extra steps for hiding the assignment from student view and hiding the grade book entry). This is not good, as it does not allow the teacher to make changes (e.g., as required to deal with marker drift or for checking across multiple markers). &lt;br /&gt;
&lt;br /&gt;
The suggestion is to add a release control to the assignment module. This will have three possibilities, visible in the assignment marking overview screen (mod/assign/view.php?id=3&amp;amp;action=grading):&lt;br /&gt;
* Nothing shown (no-one has yet saved any marking for a student)&lt;br /&gt;
* Not released (someone has saved marking, but this marking is not yet visible to the student)&lt;br /&gt;
* Released (marking is visible to the student)&lt;br /&gt;
&lt;br /&gt;
The sole focus here is on if the student can see the marking or not. This is not about trying to manage the marking process.&lt;br /&gt;
&lt;br /&gt;
This functionality is already included in supporting the marking process as proposed by the Lightwork Online project. The EAM project is interested in this functionality as well.&lt;br /&gt;
&lt;br /&gt;
PC: A concern that I have with adding a release control to the assignment module is that teachers already have a form of release control (hiding the grade book entry). It might be simpler if we could use this existing mechanism instead of adding a second release control that may confuse teachers.&lt;br /&gt;
&lt;br /&gt;
== How do these functionalities combine for the user and in implementation? ==&lt;br /&gt;
&lt;br /&gt;
The functionalities would result in three settings to the Assignment update page (course/modedit.php?update=3&amp;amp;return=1).&lt;br /&gt;
&lt;br /&gt;
* Control release of marking to students (Yes/No)&lt;br /&gt;
* Set distribution of marking (Yes/No; with Yes offering selection of groups/groupings)&lt;br /&gt;
* Manage marking process (Yes/No; with Yes offering allocation algorithms/manual allocation)&lt;br /&gt;
&lt;br /&gt;
Controlling the release of marking to students is not in conflict with setting the distribution of marking, and is already included in managing the marking process.&lt;br /&gt;
&lt;br /&gt;
Fundamentally there is no conflict between setting the distribution of marking and managing the marking process (in fact, it would be welcome as a ‘group’ will likely contain a large number of students and possibly several markers, making it very useful to be able to manage their marking). Yet, an initial implementation might keep things more simple and make these setting mutually exclusive.&lt;br /&gt;
&lt;br /&gt;
The distribution of marking will build on already existing groups and groupings. No further database tables should be necessary to capture this information. Any changes to groups would be reflected during the marking process.&lt;br /&gt;
&lt;br /&gt;
Capturing the marking allocations will require new database tables. If one allows building the allocation on groups, this will mean that the initial setting for the allocations is taken from the groups, but that any changes to groups will not be automatically reflected in marker allocations (but can be done manually, like any changes to allocations).&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;(The following sections currently do not match what is proposed under Goals above.)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
EH: Paul, with &amp;quot;Advanced marking - single marker&amp;quot;, do you see that an automated marking allocation is made to one person (who has to have the capability to release grades), therefore enforcing that only this person can mark? I think this is a quite different approach to what Damyon is proposing, which basically says &#039;use marking statuses but do not record/control who is marking&#039;. If I understand correctly what Paul is proposing, this means that one can use marking statuses only if one controls marker allocation.  This might be a better solution, as it cuts out variety, simplifying things for the development and the user. We could add a fourth option for using marking statuses without marker allocation, this might give the following options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately, marker allocations are not recorded)&lt;br /&gt;
* Advanced marking - no marker allocations&amp;quot; ((Grades are released when status changed to &#039;Released&#039;. No control who is marking)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Only single marker specified can mark and release)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;. Multiple markers work together)&lt;br /&gt;
&lt;br /&gt;
GW - I think my preference is for three settings:&lt;br /&gt;
Release grades immediately&lt;br /&gt;
Allocate markers to students&lt;br /&gt;
&lt;br /&gt;
and the third&lt;br /&gt;
Grouping for marker allocations (to appear only if group allocation is selected)&lt;br /&gt;
&lt;br /&gt;
I think it may end up being clearer, rather than trying to explain in help text what Simple marking and the Advanced marking options are.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. (GW - future dev? Implies the need for markers to be able to lock assignments while they are marking them). If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Will you be creating new groups to hold the allocations?&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: The seems to be our &#039;In marking&#039;&lt;br /&gt;
&lt;br /&gt;
GW - what about &amp;quot;Ready to mark&amp;quot; - this might be more consistent with the other statuses &amp;quot;Ready for review&amp;quot; and &amp;quot;Ready for release&amp;quot;. Is there any relationship between this status and the submission status...ie. if the submission status is &amp;quot;Draft&amp;quot; should the marking status be &amp;quot;Not ready to mark&amp;quot;, which changes to &amp;quot;Ready to mark&amp;quot; when the submission status is &amp;quot;submitted&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
&#039;Not marked&#039; &#039;In Marking&#039; (?) &#039;Ready for review&#039; &#039;Ready for release&#039; &#039; Released&#039;&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;. If statuses can be skipped..ie. as long as we don&#039;t force users through every status, then i don&#039;t think it will be a problem to have the five statuses as proposed above:&lt;br /&gt;
&#039;Not marked&#039;&lt;br /&gt;
&#039;In marking/Being marked&#039;&lt;br /&gt;
&#039;Ready for review&#039;&lt;br /&gt;
&#039;Ready for release&#039;&lt;br /&gt;
&#039;Released&#039;&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
If there are multiple markers added to a group then all markers will be able to mark assignments in that group. &lt;br /&gt;
&lt;br /&gt;
GW - If there are no markers in a group, then there is the potential that student assignments would get missed....there is no visual queue that students are unallocated. In addition - our SIS-created groups systematically check for the addition of members who are not in the group in the SIS. Any staff therefore who are added to the groups in Moodle will be removed from the group on the next update...unless we changed our integration script to retain users in SIS-created groups as long as they were not students??&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
EH: I am with Grette there - feedback should only be visible to students when marking is considered as finished (otherwise we would be back to the current deficiencies in Moodle)&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=34950</id>
		<title>Lightwork</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Lightwork&amp;diff=34950"/>
		<updated>2012-08-19T22:04:09Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* The new Lightwork web services */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Work in progress}}&lt;br /&gt;
{{Infobox Project&lt;br /&gt;
|name = Lightwork&lt;br /&gt;
|state = In Development&lt;br /&gt;
|tracker = http://tracker.moodle.org/browse/MDL-31409&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=187818&lt;br /&gt;
|assignee = Lightwork&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
Lightwork is a marking tool for managing and marking student assignments. See http://lightwork.massey.ac.nz/projects/show/fat and http://lightworkmarking.org/. It consists of a client application that was created using the Open source Eclipse Rich Client Platform see http://wiki.eclipse.org/index.php/Rich_Client_Platform and web services for communication with Moodle. Lightwork downloads and manages student submissions so that marking can be done on the client computer. It can be used offline with changes synchronized to Moodle the next time the teacher connects.&lt;br /&gt;
&lt;br /&gt;
Currently, the Lightwork web services are installed in a Moodle installation by using the [[Local_customisation|local customisations]] hook and the web services are implemented using the OKTech framework. See https://docs.moodle.org/20/en/Web_Services:OK_Tech_Web_Services. It is now proposed to add the Lightwork web services to the core Moodle 2.4 release as described in the rest of this document.&lt;br /&gt;
&lt;br /&gt;
== Using Lightwork with Moodle for offline marking ==&lt;br /&gt;
The following user stories are designed to help explain how Lightwork is used with Moodle for offline marking:&lt;br /&gt;
=== Creating a Marking Guide and setting it ready for marking ===&lt;br /&gt;
A teacher decides that they would like to use Lightwork&#039;s marking guide (introduced to Moodle in 2.3) for an assignment that they have given to their students. The teacher is a busy person who spends a lot of time out of the office without an internet connection and wants to be able to continue developing the Marking Guide in any spare moment that they have. They decide to use Lightwork to do this:&lt;br /&gt;
# In their office on their work PC the teacher begins work on the Marking Guide&lt;br /&gt;
# The teacher remembers that they will be out of the office for the next few days. There is still lots to do in order to finish the marking guide. They remember that Lightwork allows them to work offline.&lt;br /&gt;
# The teacher installs Lightwork on their new laptop. They connect to the internet and synchronize Lightwork with their Moodle instance.&lt;br /&gt;
# Within Lightwork they can now all their courses and assignments. They can see their partially completed Marking Guide.&lt;br /&gt;
# The next day, the teacher is waiting in their car to meet with a colleague and remembers the unfinished Marking Guide. They open Lightwork in their laptop and continue developing the Marking Guide in Lightwork&#039;s interface. They add/modify criteria and frequently used comments to their marking guide. When their colleague arrives they still haven&#039;t finished. The nearly completed Marking Guide is stored in Lightwork but cannot be synchronized to Moodle since there is no internet connection.&lt;br /&gt;
# After several more offline sessions, the teacher completes the marking guide&lt;br /&gt;
# The teacher arrives home at the end of the week. They want the other teachers to review their Marking Guide.&lt;br /&gt;
# The teacher connects their laptop to the internet, opens Lightwork and synchronizes it with their Moodle instance.&lt;br /&gt;
# The teacher&#039;s completed Marking Guide is now synchronized up to Moodle. Since they&#039;ve been away more students have enrolled on the Moodle course, this new information is synchronized down to Lightwork.&lt;br /&gt;
# The teacher phones the other 2 teachers who help to teach the course. The first one only uses Moodle to mark, the second only uses Lightwork. The first teacher views the Marking Guide in Moodle. The second teacher synchronizes Lightwork and views the Marking Guide.&lt;br /&gt;
# The next the teachers all get together to discuss the Marking Guide. They agree some changes which they make in Lightwork. They then set their Marking Guide ready for marking and synchronize their changes with Moodle.&lt;br /&gt;
&lt;br /&gt;
== Challenges and issues ==&lt;br /&gt;
&lt;br /&gt;
Lightwork stores marker allocation, rubrics and rubric instance information in its own table structure. This structure must be modified to integrate with and enhance Moodle.&lt;br /&gt;
&lt;br /&gt;
* Lightwork makes the use of a rubric compulsory. This is not the case in Moodle.&lt;br /&gt;
* Moodle already has the ability to define and use a rubric which was introduced in Moodle 2.2.&lt;br /&gt;
* Moodle defines its rubric in database table structure whereas Lightwork uses XML&lt;br /&gt;
* Moodle has no marker allocation capability. Lightwork&#039;s marker allocation must be introduced so that it can be used by both Moodle and Lightwork&lt;br /&gt;
&lt;br /&gt;
== Design goals ==&lt;br /&gt;
&lt;br /&gt;
=== Rubric compatibility between the Moodle rubric and Lightwork ===&lt;br /&gt;
&lt;br /&gt;
Lightwork supports 2 types of rubrics. I&#039;ll refer to these as rubric type 1 and rubric type 2. These rubrics are currently stored as XML and there is the potential to create other rubric types. Moodle has one type of rubric, the advanced grading rubric. This is equivalent to Lightwork&#039;s type 1 rubric. The type 2 rubric allows the teacher to choose a mark for a criterion as opposed to selecting from fixed defined levels. A possibility for a name for the type 2 rubric might be &#039;&#039;&#039;marking guide&#039;&#039;&#039;, see http://moodle.org/mod/forum/discuss.php?d=195738&amp;amp;parent=854867.&lt;br /&gt;
&lt;br /&gt;
Since Moodle has already implemented rubrics by using database tables instead of XML, Lightwork on Moodle will have to change to follow this approach. &lt;br /&gt;
&lt;br /&gt;
Lightwork will need to store its type 1 rubric and rubric instances using the rubric grading tables in Moodle. These tables are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_criteria&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In order to implement the type 2 rubrics we could either:&lt;br /&gt;
&lt;br /&gt;
* Create a new gradingform plugin for the type 2 rubric. This might be called gradingform_markingguide&lt;br /&gt;
* Modify the existing gradingform_rubric so that it supports the type 2 rubric. The table structure required for the type 2 rubric is very similar and differs only in that &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; would require an additional field to store the mark and &#039;&#039;&#039;mdl_gradingform_rubric_levels&#039;&#039;&#039; is not required.&lt;br /&gt;
&lt;br /&gt;
Issues:&lt;br /&gt;
&lt;br /&gt;
* The Lightwork type 1 rubric allows weightings to be defined for criteria. The Moodle rubric does not support this.&lt;br /&gt;
* All Lightwork rubrics support the use of a bank of frequently used comments. The Moodle rubric does not support this but could be extended to use this feature.&lt;br /&gt;
* It would be useful to keep the ability to store rubrics in XML format since this would allow transformation into different document types.&lt;br /&gt;
* Lightwork would need to be modified to store rubrics and rubric instances in the mdl_grading* tables&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation and rubric definitions ===&lt;br /&gt;
&lt;br /&gt;
Lightwork requires marker allocation and a rubric to be used. This was a deliberate design decision to enforce the use of rubrics. Marker allocation will be introduced as part of the new assignment module and will be compatible with Lightwork&#039;s current marking process. The following scenarios will be possible in Moodle 2.3:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Scenario in Moodle&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Impact of choosing to use Lightwork&#039;&#039;&#039;  &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the new Moodle 2.3 marker allocation process and the rubric grading method  &lt;br /&gt;
|Lightwork marking as usual but using the advanced grading rubric already created in Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|Teacher creates an assignment. They choose to use the simple grading method and no marker allocation&lt;br /&gt;
|Choosing to use Lightwork will create marker allocation. Teachers and markers can use this allocation for grading within Moodle if they choose. If Lightwork uses a type 1 rubric it will be saved using the current &#039;&#039;&#039;rubric&#039;&#039;&#039; grading definition. The teacher can now switch to the rubric grading method to take advantage of the rubric created in Lightwork. If Lightwork uses a type 2 rubric it will be saved in Moodle using the same advanced grading mechanism.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Marking and rubric grading instances ===&lt;br /&gt;
&lt;br /&gt;
Moodle uses the &#039;&#039;&#039;mdl_grading_instances&#039;&#039;&#039; and the &#039;&#039;&#039;mdl_gradingform_rubric_fillings&#039;&#039;&#039; tables to store the results achieved by the students based on the rubric. When marking a Moodle compatible rubric (Lightwork type 1 rubric) in Lightwork, the results will be stored in the same way.&lt;br /&gt;
&lt;br /&gt;
== The new proposed Lightwork and marking allocation database structures ==&lt;br /&gt;
&lt;br /&gt;
This new database structure needs to support the ability for markers (usually teachers and non-editing teachers) to allocate students to markers for the purpose of grading their work. It will be used by both Lightwork and Moodle. This will require new tables to be designed and implemented&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO - design the marking management tables&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The existing &#039;&#039;&#039;mdl_grading*&#039;&#039;&#039; tables will be used to store the Lightwork rubrics. Depending on the approach taken (see previous section) these tables may either need to be modified or a new plugin created to support the Lightwork type 2 rubric.&lt;br /&gt;
&lt;br /&gt;
== The new Moodle 2.3 assignment module ==&lt;br /&gt;
&lt;br /&gt;
In addition to adding Lightwork&#039;s web services into the Moodle core, many of Lightwork&#039;s features are being included in the Moodle 2.3 assignment module. This work is being done in conjunction with https://docs.moodle.org/dev/Assignment. The new features are:&lt;br /&gt;
&lt;br /&gt;
* An additional type of rubric that allows markers to specify the mark given for a criterion. This differs from the current rubric where the marker must select from one or more fixed marks. We are currently undecided on the best name for this type of rubric. We are currently calling it a &#039;&#039;&#039;Marking guide&#039;&#039;&#039;.&lt;br /&gt;
* Frequently used comments. A bank of Frequently used comments can be defined for a rubric. Markers can select and add these comments when providing feedback based on a rubric.&lt;br /&gt;
* Marking management. A marking manager can allocate students to markers. A marking process is used to ensure consistency of marking.&lt;br /&gt;
* Team submission. Students work as a team and submit a single team submission.&lt;br /&gt;
&lt;br /&gt;
== The old Lightwork Database structures ==&lt;br /&gt;
=== lw_rubric ===&lt;br /&gt;
Each record in this table represents a marking rubric that has been created in the Lightwork client. Each rubric is associated with an activity. It is possible to have multiple rubrics per activity. The rubric data is represented in XML which is stored in the xmltext field.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Allow Null&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Info&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|autoincrementing. Required by Moodle &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;lwid&#039;&#039;&#039;&lt;br /&gt;
|int(3)&lt;br /&gt;
|false&lt;br /&gt;
|Allows multiple rubrics for an activity. The id field cannot be used since these records may be created offline on the Lightwork client&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;activity&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The associated activity&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;activitytype&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The associated activity type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xmltext&#039;&#039;&#039;&lt;br /&gt;
|text&lt;br /&gt;
|false&lt;br /&gt;
|The XML rubric&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;complete&#039;&#039;&#039;&lt;br /&gt;
|int(1)&lt;br /&gt;
|false&lt;br /&gt;
|This value defaults to false on creation of the record. It is set to true when the teacher has finshed creating the rubric and it is ready for release to the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;deleted&#039;&#039;&#039;&lt;br /&gt;
|int(1)&lt;br /&gt;
|false&lt;br /&gt;
|Defaults to false on creation. Setting to true indicates logical deletion.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;timemodified&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|The time when record was last updated&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== lw_marking ===&lt;br /&gt;
Each record in this table represents the allocation of a marker to a student and holds the marking sheet as XML. The marking sheet is based on the associated rubric record.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Allow Null&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Info&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|autoincrementing. Required by Moodle. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;marker&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The user doing the marking&lt;br /&gt;
 &lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;student&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The student being marked&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;xmltext&#039;&#039;&#039;&lt;br /&gt;
|text&lt;br /&gt;
|false&lt;br /&gt;
|The XML marking sheet based on the associated rubric&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;activity&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The associated activity&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;activitytype&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The associated activity type&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;statuscode&#039;&#039;&#039;&lt;br /&gt;
|char(2)&lt;br /&gt;
|false&lt;br /&gt;
|The status of the marking as defined by the records in the lw_marking_status table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;rubric&#039;&#039;&#039;&lt;br /&gt;
|int(3)&lt;br /&gt;
|false&lt;br /&gt;
|The associated rubric lwid from lw_rubric&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;deleted&#039;&#039;&#039;&lt;br /&gt;
|int(1)&lt;br /&gt;
|false&lt;br /&gt;
|Defaults to false on creation. Setting to true indicates logical deletion.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;timemodified&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|The time when record was last updated&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== lw_marking_history ===&lt;br /&gt;
Multiple records in this table are associated with a single marking record in lw_marking. They represent the history of the marking process from the assignment of the marker to the student up to the release of the marking to the Moodle grade book.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Allow Null&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Info&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|autoincrementing. Required by Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;lwid&#039;&#039;&#039;&lt;br /&gt;
|int(3)&lt;br /&gt;
|false&lt;br /&gt;
|Each marking history belong to a marking is uniquely identified by this field. The id field cannot be used since these records may be created offline on the client&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;marker&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The user doing the marking&lt;br /&gt;
 &lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;student&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The student being marked&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;activity&#039;&#039;&#039;&lt;br /&gt;
|int(10)&lt;br /&gt;
|false&lt;br /&gt;
|The associated activity&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;statuscode&#039;&#039;&#039;&lt;br /&gt;
|char(2)&lt;br /&gt;
|false&lt;br /&gt;
|The status of the marking as defined by the records in the lw_marking_status table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;rubric&#039;&#039;&#039;&lt;br /&gt;
|int(3)&lt;br /&gt;
|false&lt;br /&gt;
|The associated rubric lwid from lw_rubric&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;comment&#039;&#039;&#039;&lt;br /&gt;
|char(255)&lt;br /&gt;
|false&lt;br /&gt;
|A comment about this status change&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;timemodified&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|The time when record was last updated&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== lw_marking_status ===&lt;br /&gt;
The records in this table represent all possible marking statuses. The stauses currently used are:&lt;br /&gt;
&lt;br /&gt;
# AL - Allocated&lt;br /&gt;
# MA - In marking&lt;br /&gt;
# MF - Marking Finished&lt;br /&gt;
# RV - In review&lt;br /&gt;
# RD - Reviewed&lt;br /&gt;
# RL - Released&lt;br /&gt;
# ED - Inactive&lt;br /&gt;
# AR - Archived&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Allow Null&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Info&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;id&#039;&#039;&#039; &lt;br /&gt;
|int(10)  &lt;br /&gt;
|false&lt;br /&gt;
|autoincrementing. Required by Moodle&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;statuscode&#039;&#039;&#039;&lt;br /&gt;
|char(2)&lt;br /&gt;
|false&lt;br /&gt;
|The marking status code&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;shortdescription&#039;&#039;&#039;&lt;br /&gt;
|char(10)&lt;br /&gt;
|false&lt;br /&gt;
|A short description of this status&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;longdescription&#039;&#039;&#039;&lt;br /&gt;
|char(20)&lt;br /&gt;
|false&lt;br /&gt;
|A long description of this status&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== The new Lightwork web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the Moodle web services with the REST protocol. The login and password mechanism in the old web services is being replaced by tokens. Token based authentication is replacing password based authentication in Moodle.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;methodname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classname&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;classpath&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;parameters&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;type&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;description and comments&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_webservice_get_site_info&#039;&#039;&#039; &lt;br /&gt;
|core_webservice_external  &lt;br /&gt;
|webservice/externallib.php&lt;br /&gt;
|None&lt;br /&gt;
|read&lt;br /&gt;
|This is required to ensure that the Lightwork client is compatible with the Moodle version it is calling. This existing Moodle function returns a build number for each web service function. Currently, for core web services, the function just returns the build number in the main version.php file. This function needs to be modified to return the release number and the version number. The release number is a user friendly number that the client can display and it indicates the Moodle version number for which the current version of the client has been designed to function. When the client detects that the Moodle version has changed, the client will either automatically update itself or it will prompt the user to perform the update to match the Moodle version to which it is connecting.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_assignments&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|courseids (optional), capabilities (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31683 Return list of courses and assignments that this user has a particular capability in.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_users_get_users_with_capability&#039;&#039;&#039;&lt;br /&gt;
|core_course_external&lt;br /&gt;
|course/externallib.php &lt;br /&gt;
|List of course ids, Flag to specify whether all students are returned or just the ones that have submitted a submissions. List of capabilities to filter the results. &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31859 Return list of participants to specified courses. This should include students and teachers. User details are returned together with capabilities.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_submissions&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php &lt;br /&gt;
|List of assignment ids (required), status (optional), since (optional), before (optional) &lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31682 Return assignment submissions for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;mod_assign_get_grades&#039;&#039;&#039;&lt;br /&gt;
|mod_assign_external&lt;br /&gt;
|mod/assign/externallib.php&lt;br /&gt;
|List of assignment ids (required), since (optional)&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31873 Return assignment grades (from the assign_grades table) for the specified assignments&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;core_grade_get_rubric_grading_definitions&#039;&#039;&#039;&lt;br /&gt;
|core_grade_external&lt;br /&gt;
|grade/externallib.php &lt;br /&gt;
|List of grading area ids&lt;br /&gt;
|read&lt;br /&gt;
|http://tracker.moodle.org/browse/MDL-31681 This is equivalent to the old getMarkingRubrics method. It returns the details for the &#039;rubric&#039; grading definitions from the &#039;&#039;&#039;mdl_grading_definitions&#039;&#039;&#039; table and the &#039;&#039;&#039;mdl_gradingform*&#039;&#039;&#039; tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Migration of existing SOAP OKtech web services to Moodle core web services ==&lt;br /&gt;
&lt;br /&gt;
These web services use the OKtech SOAP implementation. They are being replaced by the Moodle web services described in the previous section.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Operation name&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Input message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Output message&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Modifications for migration to Moodle core web services&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;login&#039;&#039;&#039; &lt;br /&gt;
|username, password  &lt;br /&gt;
|the session key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;logout&#039;&#039;&#039;&lt;br /&gt;
|session key&lt;br /&gt;
|true or false&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getPublicKey&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|the public key&lt;br /&gt;
|No longer required. Moodle&#039;s token authentication will be used&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getServiceVersion&#039;&#039;&#039;&lt;br /&gt;
|empty&lt;br /&gt;
|The Lightwork web services version number&lt;br /&gt;
|We will use the Moodle version number instead. This is returned by calling service core_webservice_get_site_info&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourses&#039;&#039;&#039;&lt;br /&gt;
|the session key&lt;br /&gt;
|An array of 0 or more course records. An array of 0 or more error messages.&lt;br /&gt;
|We will no longer use capabilities. Instead we will use the &#039;&#039;&#039;teacher&#039;&#039;&#039; and &#039;&#039;&#039;non editing teacher&#039;&#039;&#039; roles which will be the &#039;&#039;&#039;marking manager&#039;&#039;&#039; and &#039;&#039;&#039;marker&#039;&#039;&#039; respectively&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getCourseParticipants&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of course ids, allStudents(boolean) &lt;br /&gt;
|An array of 0 or more course participant records. An array of 0 or more error messages.&lt;br /&gt;
|when allStudents is true, all course particpants students are returned, otherwise only students that have submitted work are included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getTeams&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of assignment ids, a list of team ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more team records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, allStudents(boolean)&lt;br /&gt;
|An array of 0 or more records from the assignment_submissions table, an array of 0 or more error messages.&lt;br /&gt;
|When allStudents is set to true, draft submissions are not included&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of activity ids, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of 0 or more records from the lw_rubric table, an array of 0 or more error messages.&lt;br /&gt;
|The timemodified parameter can be used to reduce the number of records returned when the client knows they have already received updates for all rubrics at a certain point in time.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveRubrics&#039;&#039;&#039;&lt;br /&gt;
|the session key, an array of rubric records&lt;br /&gt;
|An array of saved rubric records, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_rubric table with new and updated rubrics&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getFeedbackSubmissions&#039;&#039;&#039;&lt;br /&gt;
|the session key, an activity id, a timemodified value &amp;gt;=0&lt;br /&gt;
|An array of feedback submission records, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the feedback assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getUserInfo&#039;&#039;&#039;&lt;br /&gt;
|The session key, a multi-dimensional array with user ids associated with a timemodified value &amp;gt;=0, an assignment id&lt;br /&gt;
|An array of user_info records, an array of 0 or more error messages.&lt;br /&gt;
|Returns information from the user_info_data for a category in the user_info_category table&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getModifiedMarkingCount&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of activity ids, the marking type, a timemodified value &amp;gt;=0&lt;br /&gt;
|The number of records in the lw_marking table modified after timemodified&lt;br /&gt;
|Used to prevent making queries on the lw_marking table when there are no new records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getmarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, an activity id, the marking type, a timemodified value &amp;gt;=0, allstudents(boolean)&lt;br /&gt;
|An array of records from the lw_marking table, an array of 0 or more error messages.&lt;br /&gt;
|Returns records from lw_marking for the specified activity id that have been modified after the specified timemodified value&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getMarkingHistory&#039;&#039;&#039;&lt;br /&gt;
|The session key, the marking type, an array of unique marking identifiers&lt;br /&gt;
|An array of records from the lw_marking_history table, an array of 0 or more error messages.&lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;saveMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type, allstudents(boolean)&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Updates the lw_marking and lw_marking_history table with new and updated marking and marking history records&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|Releases the marking to the Moodle grade book. Also uploads marking feedback as attachments. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;releaseTeamMarking&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of lw_marking records, the marking type&lt;br /&gt;
|An array of unique marking identifiers, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used when the team assignment type has been installed&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;uploadAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, array of assignment ids associated with a file reference&lt;br /&gt;
|an array of 0 or more error messages&lt;br /&gt;
|Uploads file attachments for the specified assignments. The file attachments can be any documents that have been annotated during marking and PDF rubrics for the students&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;downloadAssignmentDocumentsMetaData&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, includeannotatedfiles&lt;br /&gt;
|An array of metadata about the files stored for the assignment, an array of 0 or more error messages.&lt;br /&gt;
|This web service is used by the Lightwork client to decide whether to replace or upload its own local versions of the files&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;repairLightworkData&#039;&#039;&#039;&lt;br /&gt;
|The session key, an array of assignment ids&lt;br /&gt;
|An array of unique identifiers for records that were deleted, an array of 0 or more error messages.&lt;br /&gt;
|Database records such as assignments and users may be deleted or updated in Moodle at any time. This web service can be called by the Lightwork client when it suspects that data has become invalid. The returned results are used to update the Lightwork client&#039;s data model. For example, if a teacher unenrolls from a course then they no longer have permissions to view this course and it must be removed from the Lightwork client&#039;s local database.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getAssignmentDocuments&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, assignment id, an array of filenames to be downloaded&lt;br /&gt;
|An array of file references, an array of 0 or more error messages&lt;br /&gt;
|Downloads files as attachments which are accessed using the file references&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionReport&#039;&#039;&#039;&lt;br /&gt;
|The session key, course id, start date, end date&lt;br /&gt;
|An array of submission report records, an array of 0 or more error messages&lt;br /&gt;
|Downloads information about all student submissions for a course between a specified time period. This information is used by the Lightwork client to produce a submission report.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;getSubmissionFiles&#039;&#039;&#039;&lt;br /&gt;
|The session key, the activity id, an array of submission ids&lt;br /&gt;
|An array of assignment_submissions table records with file references, an array of 0 or more error messages &lt;br /&gt;
|An array of records from the assignment_submissions table with references to a zip file attachment containing files submitted by the student&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Capabilities and permissions ==&lt;br /&gt;
&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers  -  create and modify rubrics, allocate markers to students, release marks to the gradebook&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions - Mark student submissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Normally, capabilities would be set up as follows:&lt;br /&gt;
&lt;br /&gt;
Teacher role&lt;br /&gt;
* moodle/lightwork:managelightworkmarkers&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
Non-editing teacher role&lt;br /&gt;
* moodle/lightwork:marklightworksubmissions&lt;br /&gt;
* webservice:createtoken&lt;br /&gt;
* webservice/soap:use&lt;br /&gt;
&lt;br /&gt;
== Administration and configuration ==&lt;br /&gt;
&lt;br /&gt;
The change to use the core Lightwork web services will be transparent to Lightwork users. However, the Moodle administrator will need to configure the services as follows:&lt;br /&gt;
&lt;br /&gt;
* Enable Web services in the &#039;&#039;&#039;Site Administration - Advanced features&#039;&#039;&#039; page&lt;br /&gt;
* Enable the SOAP protocol in the &#039;&#039;&#039;Site Administration - Plugins - Web services - Manage protocols&#039;&#039;&#039; page&lt;br /&gt;
* Add a new custom external service in the &#039;&#039;&#039;Site Administration - Plugins - Web services - External services&#039;&#039;&#039; page&lt;br /&gt;
** Name - Lightwork&lt;br /&gt;
** Enabled - Checked&lt;br /&gt;
** Authorised users only - Unchecked&lt;br /&gt;
** Required capability - No required capability&lt;br /&gt;
* Select &#039;&#039;&#039;Add Service&#039;&#039;&#039; to add the new Lightwork web service&lt;br /&gt;
* Select the &#039;&#039;&#039;Functions&#039;&#039;&#039; link of the new Lightwork web service&lt;br /&gt;
* Select &#039;&#039;&#039;Add Functions&#039;&#039;&#039; and add all the functions that are prefixed with &#039;&#039;&#039;lightwork_&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Assuming that the correct capabilities have been setup for them as described in the capabilities section, Lightwork users will now be able to connect to Moodle.&lt;br /&gt;
&lt;br /&gt;
== Moodle APIs used by Lightwork in Moodle 2.1 ==&lt;br /&gt;
&lt;br /&gt;
* mod/assignment/lib.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/assignment/type/&amp;lt;assignment type&amp;gt;/assignment.class.php (will be replaced with mod_assign in Moodle 2.3)&lt;br /&gt;
* mod/resource/locallib.php&lt;br /&gt;
* lib/dml/moodle-database.php&lt;br /&gt;
* lib/accesslib.php&lt;br /&gt;
* lib/grade/&lt;br /&gt;
* lib/uploadlib.php&lt;br /&gt;
* lib/filebrowser/&lt;br /&gt;
* lib/filestorage/&lt;br /&gt;
&lt;br /&gt;
== User Interface - Create assignment, define Marking guide and mark student work according to Marking guide ==&lt;br /&gt;
=== Create and update assignment ===&lt;br /&gt;
&lt;br /&gt;
[[File:UpdateAssignment.png|600px|thumb|center|Create and update assignment page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading, Define Marking guide page ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Define Marking guide&#039;&#039;&#039; under &#039;&#039;&#039;Settings-Assignment administration-Advanced grading&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
[[File:UpdateRubric.png|600px|thumb|center|Advanced grading, Define Marking guide page]]&lt;br /&gt;
&lt;br /&gt;
=== Advanced grading page with active grading method &#039;&#039;&#039;Marking guide&#039;&#039;&#039; ===&lt;br /&gt;
&lt;br /&gt;
The marking manager selects &#039;&#039;&#039;Advanced grading&#039;&#039;&#039; under the &#039;&#039;&#039;Settings-Assignment administration&#039;&#039;&#039; link&lt;br /&gt;
&lt;br /&gt;
[[File:LookAtRubric.png|600px|thumb|center|Advanced grading page with active grading method marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Mark student using the Marking guide ===&lt;br /&gt;
&lt;br /&gt;
The marker selects the student submission from the submissions page and chooses to start marking&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_2.png|600px|thumb|center|Mark student using the Marking guide]]&lt;br /&gt;
&lt;br /&gt;
=== Student views their feedback ===&lt;br /&gt;
&lt;br /&gt;
The marking manager has reviewed and released the marks to the student. The student logs in and views their feedback.&lt;br /&gt;
&lt;br /&gt;
[[File:StudentView.png|600px|thumb|center|Student views their feedback]]&lt;br /&gt;
&lt;br /&gt;
== User Interface - Marker allocation and management ==&lt;br /&gt;
&lt;br /&gt;
=== Select to use marker allocation in this assignment ===&lt;br /&gt;
&lt;br /&gt;
=== Allocate markers to students ===&lt;br /&gt;
&lt;br /&gt;
The teacher commences allocating markers to students&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_1.png|600px|thumb|center|Allocate markers to students]]&lt;br /&gt;
&lt;br /&gt;
=== Review the marking ===&lt;br /&gt;
&lt;br /&gt;
This assumes that this assignment is being marked using the new &amp;quot;marking guide&amp;quot; advanced grading method&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_3.png|600px|thumb|center|Review the marking]]&lt;br /&gt;
&lt;br /&gt;
=== Release the marking ===&lt;br /&gt;
&lt;br /&gt;
[[File:ViewSubmittedAssignments_4.png|600px|thumb|center|Release the marking]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Marking guide - Screenshot and Testing ==&lt;br /&gt;
=== Screenshots (to come) ===&lt;br /&gt;
&lt;br /&gt;
=== Call for testing ===&lt;br /&gt;
&lt;br /&gt;
Please help us with testing the marking guide functionality.&lt;br /&gt;
&lt;br /&gt;
Link to marking guide code: https://github.com/Lightwork-Marking/moodle-gradingform_guide&lt;br /&gt;
&lt;br /&gt;
A test plan is available from: [http://lightwork.massey.ac.nz/documents/show/6 TestPlan_MarkingGuide]&lt;br /&gt;
&lt;br /&gt;
Testing results can be recorded in: [http://lightwork.massey.ac.nz/documents/show/6 Testing_Record_MarkingGuide]&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=34910</id>
		<title>Assignment Advanced Marking</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Assignment_Advanced_Marking&amp;diff=34910"/>
		<updated>2012-08-17T02:18:13Z</updated>

		<summary type="html">&lt;p&gt;Pcharsle: /* Marker allocations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a proposal for additional marking features in the Assignment module. &lt;br /&gt;
&lt;br /&gt;
References: https://docs.moodle.org/dev/Lightwork#User_Interface_-_Marker_allocation_and_management&lt;br /&gt;
&lt;br /&gt;
Tracker Issue: http://tracker.moodle.org/browse/MDL-34902&lt;br /&gt;
&lt;br /&gt;
= Goals and rationale =&lt;br /&gt;
&lt;br /&gt;
The main goals of this change are to:&lt;br /&gt;
&lt;br /&gt;
* Enable dividing the marking of large classes among multiple markers&lt;br /&gt;
* Enable markers to review each others marking before releasing marks to students&lt;br /&gt;
* Enable markers to review their own marking before releasing marks to students&lt;br /&gt;
* Not add any additional complexity for people who do not need these features&lt;br /&gt;
&lt;br /&gt;
= Overview =&lt;br /&gt;
&lt;br /&gt;
== Settings added to the mod_assign settings page ==&lt;br /&gt;
&lt;br /&gt;
Release grades immediately (Checkbox, default to on - this is the current behaviour)&lt;br /&gt;
&lt;br /&gt;
[Help text] When enabled, grades will be visible to students as soon as they have been entered by a grader (If the grade column is visible in the gradebook). When disabled, any grades that are entered will be only visible to graders until they are approved for release.&lt;br /&gt;
&lt;br /&gt;
Allocate markers to students (Select list of options, &amp;quot;None - all markers can mark all students&amp;quot;, &amp;quot;Manually allocated - markers are manually allocated students to mark&amp;quot;, &amp;quot;Groups - Markers can mark students in their own group&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When the grouping method is chosen above, an additional setting should be enabled to allow a grouping to be specified for the marker allocations.&lt;br /&gt;
&lt;br /&gt;
Grouping for marker allocations (Select from the available groupings - or None for all groups)&lt;br /&gt;
&lt;br /&gt;
GW - we currently create marking groups using the groups interface and then set assignment up using &amp;quot;Separate groups&amp;quot; so that markers can filter the list of assignments. One of the issues we have come up against is unenrolled (suspended) students still appearing in the groups interface. We have a proposal for better management of suspended users. We have identified 23 (possibly 25) areas where suspended users are currently an issue. Where possible, we’d like an option to toggle between hiding and showing suspended users, with the default option being hidden. We are looking to resource a change that will be all encompassing and a complete fix that can be contributed back to the Moodle community. Initially we will build for 2.1.6, but will then review for 2.3 towards the end of the year.&lt;br /&gt;
&lt;br /&gt;
PC - I believe the assignment settings should be simplified or teachers will find it confusing. I would like to see the &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; replaced with a single drop down of standard options:&lt;br /&gt;
&lt;br /&gt;
* Simple marking&amp;quot; (the default settings - grades are released immediately)&lt;br /&gt;
* Advanced marking - single marker&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
* Advanced marking - multiple markers&amp;quot; (Grades are released when status changed to &#039;Released&#039;)&lt;br /&gt;
&lt;br /&gt;
Note that when choosing &amp;quot;Advanced marking - multiple markers&amp;quot; the teacher would be able choose whether or not to use a Grouping for allocating&lt;br /&gt;
markers. If we are going to allow other combinations of &amp;quot;Release grades immediately&amp;quot; and &amp;quot;Allocate markers to students&amp;quot; then we could have an additional menu item to allow teachers to choose their own combination.&lt;br /&gt;
&lt;br /&gt;
== Changes to grading/grading interface ==&lt;br /&gt;
&lt;br /&gt;
=== Marking release ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Release grades immediately&amp;quot; is not enabled, an additional status should be added to the grading status column &amp;quot;Draft/Ready for release/Released&amp;quot;. Use background colors as well to visually distinguish the statuses (Blue - draft, Fushia - Ready for Review, Yellow - Ready for Release, Green - Released).&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:grade capability would be able to move the status from &amp;quot;Draft&amp;quot; to &amp;quot;Ready for Review&amp;quot; via the drop down menu on each submission, or via the batch operations form.&lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; to &amp;quot;Ready for Release&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Anyone with mod/assign:releasegrade (new) capability would be able to move the grade from either &amp;quot;Draft&amp;quot; or &amp;quot;Ready for Review&amp;quot; or &amp;quot;Ready for Release&amp;quot; to &amp;quot;Released&amp;quot;. At this point the grade is pushed to the gradebook and made visible to the student.&lt;br /&gt;
&lt;br /&gt;
=== Marker allocations ===&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;Allocate markers to students&amp;quot; is set to &amp;quot;Manually allocated&amp;quot;, and the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of markers allocated to each student needs to be shown in a new column in the grading interface.&lt;br /&gt;
&lt;br /&gt;
Multiple markers should be able to be allocated to a single student. If the current user has mod/assign:allocategraders permission, a red X next to each markers will allow immediately removing this marker (Ajax if possible - don&#039;t refresh the full page)&lt;br /&gt;
An option should be added to the menu for each submission and the batch operations menu which takes you to a separate page where you can choose from the users with mod/assign:grade permission to allocate to a student (or multiple students). &lt;br /&gt;
&lt;br /&gt;
Any student with no markers allocated should have &amp;quot;No markers&amp;quot; in this column and the column background should be shown in a different colour (Red?) to indicate that no-one has been assigned to mark this submission. If the current user has &amp;quot;mod/assign:allocatemarkers&amp;quot; and &amp;quot;mod/assign:grade&amp;quot; capability, there should be an entry in the menu for this submissions for &amp;quot;Assign to me&amp;quot; (preferably AJAX - do not refresh entire page).&lt;br /&gt;
&lt;br /&gt;
If the a submissions has not been allocated to the current user, the option to grade that submission is removed. &lt;br /&gt;
&lt;br /&gt;
If the current user does not have &amp;quot;mod/assign:allocatemarkers&amp;quot; capability, the list of submissions will be limited to only show the submissions where the current user has been allocated as a marker.&lt;br /&gt;
&lt;br /&gt;
PC - How will you be handling marker allocation in the database when &amp;quot;Grouping for allocating markers&amp;quot; isn&#039;t selected? Will you be creating new groups to hold the allocations?&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they do not wish to use advanced marking ===&lt;br /&gt;
* Create an assignment and leave the new settings at their defaults&lt;br /&gt;
** Release grades immediately: &amp;quot;checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
=== Teacher is creating an assignment with a small number of students and they wish to mark all submissions, then re-mark several submissions to check for &amp;quot;grading drift&amp;quot; before release ===&lt;br /&gt;
(I am defining this as the perception of quality changing over time as the marker marks each assignment in turn - can&#039;t find a good reference right now)&lt;br /&gt;
EH: This is called &#039;marker drift&#039;. you&#039;ll find a brief description in http://etools.massey.ac.nz/documents/LitReview101006.pdf (p. 19 bottom), as well as references to further literature.&lt;br /&gt;
* Teacher has &amp;quot;mod/assign:create&amp;quot;, &amp;quot;mod/assign:grade&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* Create an assignment and de-select Release grades immediately&lt;br /&gt;
** Release grades immediately: &amp;quot;not checked&amp;quot;&lt;br /&gt;
** Allocate markers to students: &amp;quot;None&amp;quot;&lt;br /&gt;
* Teacher marks each submission individually. Grades are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
GW - I think I know why this status is &amp;quot;Draft&amp;quot;, but I think it might get confused with the submission status in the interface. I think we can come up with a better term..not that I have thought of one yet.&lt;br /&gt;
&lt;br /&gt;
PC - How about &amp;quot;Provisional&amp;quot;?&lt;br /&gt;
* Teacher re-marks a random sample of submissions&lt;br /&gt;
* Teacher releases all the grades via the batch operations form&lt;br /&gt;
&lt;br /&gt;
EH: &lt;br /&gt;
&lt;br /&gt;
I think we should point out as the main reason for the stepped release of grades via the transition from &#039;Ready for release&#039; to &#039;Released&#039; as&lt;br /&gt;
* The teacher wants to release marking to all students at the same time.&lt;br /&gt;
&lt;br /&gt;
Marker drift or any other checking done by one person on their own marking is important. Yes, in this use case the teacher can use the statuses proposed for that, yet the need for this type of checking applies to all markers (teachers and teaching assistants). This is why we have proposed the statuses of &#039;In marking&#039; and &#039;Marking finished&#039;, before the marking is being passed on the the teacher for further quality review (e.g., to check across markers).&lt;br /&gt;
&lt;br /&gt;
PS: The descriptions here focus on the release of grades - this portraits a very summative viewpoint; it does not acknowledge the importance of feedback (as in the comments hopefully written to guide the students). This is why I tend to talk about marking and marking results.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Teachers are marking submissions for the same assignment and they want to know who is marking which assignment ===&lt;br /&gt;
* Assignment has been created and there are multiple markers with &amp;quot;mod:assign/grade and mod:assign/allocatemarker&amp;quot; capabilities&lt;br /&gt;
* Each marker selects &amp;quot;Assign to me&amp;quot; for the submissions they wish to mark. &lt;br /&gt;
* Each marker then provides grades and feedback which is released immediately to students&lt;br /&gt;
* The markers can see which students have been allocated a marker and will not end up marking the same student&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 1===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Manually&lt;br /&gt;
* The teacher allocates a set of students to each of the Teaching Assistants&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to have an option on the settings page where the teacher can set if the Teaching Assistants can see the marking done by other markers (not just the grade). Is the current proposal that a Teaching Assistant would see the entries for students not allocated to them (that means that can see the grade given by another Teaching Assistant)? There would have to be a &#039;read-only&#039; grading option, allowing the Teaching Assistant to view marking done by others but not change it.&lt;br /&gt;
DW: No the current proposal is that they would not see any students not allocated to them. &lt;br /&gt;
&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
&lt;br /&gt;
EH: Here it would be nice if the Teaching Assistant could pass on a message to the Teacher together with the status change.&lt;br /&gt;
&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
&lt;br /&gt;
EH: How will the screenshot look? Will the Teacher have access to the grading interface even if the Teacher is not allocated to mark (the Teacher will have to look at the marking details, not just at the grade)?&lt;br /&gt;
DW: yes they would see the grading interface &lt;br /&gt;
If the Teacher changes feedback or grade, will this mean an automated re-allocation to the Teacher as marker? &lt;br /&gt;
DW: The teacher would not be able to provide grades or feedback unless they were the allocated marker&lt;br /&gt;
Will the student see who has marked them (there probably should be a setting allowing the Teacher to decide)? &lt;br /&gt;
DW: This is a big change - it would currently show them the last person to mark them.&lt;br /&gt;
We also need to options here to return the marking to the Teaching Assistant (ideally with comments, explaining why) and to allocate another marker (who then will continue with the marking already started - maybe this is already covered).&lt;br /&gt;
DW: This is quite an advanced workflow - we need to make sure we are not adding too much complexity (it is not prevented by this interface - it just does not include any statuses for it - ie &amp;quot;Needs allocation to another marker for a second round of marking&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
EH: This description skips the step of the Teacher taking assignments into &#039;Ready for release&#039; after successful quality checking.&lt;br /&gt;
&lt;br /&gt;
* The teacher changes the status of the grades to &#039;Released&#039;  when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
EH: I think this should read: The Teacher changes the status from &#039;Ready for review&#039; to &#039;Ready for Release&#039; when they are satisfied with the grading quality. &lt;br /&gt;
&lt;br /&gt;
Then the next step is: The Teacher changes the status from &#039;Ready for Release&#039; to &#039;Released&#039;  when they want to release marking to students.&lt;br /&gt;
&lt;br /&gt;
DW: I have added the &amp;quot;ready for release&amp;quot; status - but this will require good help explaining the difference between the statuses to teachers. A visual flow chart of the statuses would help.&lt;br /&gt;
&lt;br /&gt;
GW - I think that the Teacher should have the option to skip the &amp;quot;Ready for Release&amp;quot; status and take the assignment from &amp;quot;Ready for review&amp;quot; straight to &amp;quot;Released&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== A teacher has assistants helping them mark and wants to review all marks before they are released 2 ===&lt;br /&gt;
* Assignment has been created and there are is a teacher with &amp;quot;mod/assign:grade&amp;quot;, &amp;quot;mod/assign:allocatemarker&amp;quot; and &amp;quot;mod/assign:releasegrades&amp;quot; capabilities&lt;br /&gt;
* There are multiple teaching assistants who have &amp;quot;mod/assign:grade&amp;quot; capability but not &amp;quot;mod/assign:releasegrades&amp;quot; or &amp;quot;mod/assign:allocatemarker&amp;quot; capabilities&lt;br /&gt;
* There are groups containing teaching assistants and sets of students contained in a grouping.&lt;br /&gt;
* The Teacher configures the assignment to have:&lt;br /&gt;
** Release grades immediately : not checked&lt;br /&gt;
** Allocate markers to students : Groups&lt;br /&gt;
** Grouping for marker allocation : &amp;quot;Name of Grouping&amp;quot;&lt;br /&gt;
* The teaching assistants login and can only grade their own students. The grades and feedback are &amp;quot;Draft&amp;quot; and not released to gradebook or students&lt;br /&gt;
* When finished, for each submission the teaching assistant changes the status of the grades to &amp;quot;Ready for review&amp;quot;&lt;br /&gt;
* The teacher can see which grades/feedback are ready for them to review by the grading status.&lt;br /&gt;
* The teacher reviews all grades and feedback that are &amp;quot;Ready for review&amp;quot;, making changes if necessary&lt;br /&gt;
* The teacher changes the status of the grades to &amp;quot;Released&amp;quot; when they are satisfied with the grading quality.&lt;br /&gt;
&lt;br /&gt;
GW - what would happen if there is more than one marker in a group? what would happen if there are no markers in a group?&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers which to separately mark the same set of students and then a moderator either takes an average or chooses one of the marks to be released ===&lt;br /&gt;
Not supported by this proposal&lt;br /&gt;
&lt;br /&gt;
=== Multiple markers mark one student in sequence ===&lt;br /&gt;
&lt;br /&gt;
EH: This is about two or more markers marking student work, e.g., marker 1 marks parts 1 and 2, marker 2 marks parts 3 and 4 of an assignment. This could be done with a different form of allocation: marker1 picks a student and then marks their part; the interface shows that marker 1 has done their part, marker2 can now allocate themselves and continue the marking. Once all markers involved (as setup initially, here markers 1 and 2 need to mark) have done their parts the status changes to &#039;ready for review&#039;.&lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Separate release of grades and feedback ===&lt;br /&gt;
&lt;br /&gt;
EH: It would be nice to be able to release feedback (for formative purposes) first and marks/grades later (with a time delay or triggered by the Teacher, or, more sophisticated, dependent on the student doing something). &lt;br /&gt;
&lt;br /&gt;
This is not part of the current proposal.&lt;br /&gt;
&lt;br /&gt;
DW: I think it should be - but I don&#039;t what to make it complicated. I think that either the feedback is visible to the student during the entire marking process and they get the grade at the end - or they see nothing and they get the grades + feedback at the end (we could add those 2 options to the settings page). Note: The submission comments are visible to staff and students for the entire duration and provide 2 way comments between students and staff.&lt;br /&gt;
&lt;br /&gt;
GW: The potential issue with this is that feedback might change during the marking process. Is a student-triggered process (ie. viewing the feedback) to release grades &amp;quot;complicated&amp;quot;?&lt;br /&gt;
&lt;br /&gt;
== User Interface ==&lt;br /&gt;
=== Assignment settings screen ===&lt;br /&gt;
[[File:assign-advgrading-settings.png| Assignment settings screen]]&lt;br /&gt;
=== Submission menu in grading table ===&lt;br /&gt;
[[File:assign-advgrading-gradingmenu.png| Submission grading menu]]&lt;br /&gt;
=== Batch operations menu ===&lt;br /&gt;
[[File:assign-advgrading-gradingbatchmenu.png| Grading batch operations menu]]&lt;br /&gt;
&lt;br /&gt;
GW: Will there be an option for the Teacher with &amp;quot;mod/assign:releasegrades&amp;quot; capability to take all assignments that are in &amp;quot;Ready for Review&amp;quot; to either &amp;quot;Ready for Release&amp;quot; or &amp;quot;Release&amp;quot; without having to individually select them?&lt;br /&gt;
&lt;br /&gt;
GW - will there be a batch operation for &amp;quot;Assign to me?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Marker allocation ===&lt;br /&gt;
Notes: The current user is &amp;quot;Grader Gary&amp;quot; so the grade option has disappeared for all submissions that this user is not assigned to mark. The current user also has permission to assign graders so they see additional options in the submission menu.&lt;br /&gt;
&lt;br /&gt;
[[File:assign-advgrading-marker-allocation.png| Marker allocation]]&lt;br /&gt;
&lt;br /&gt;
== Database Changes ==&lt;/div&gt;</summary>
		<author><name>Pcharsle</name></author>
	</entry>
</feed>