MDL-12886 more external users api - untested
[moodle.git] / user / externallib.php
CommitLineData
ef22c1b6 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * External user API
20 *
21 * @package moodlecore
22 * @subpackage webservice
551f4420 23 * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
ef22c1b6 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27require_once("$CFG->libdir/externallib.php");
28
29class moodle_user_external extends external_api {
30
7b472b32
PS
31 /**
32 * Returns description of method parameters
33 * @return external_function_parameters
34 */
d4e13355 35 public static function create_users_parameters() {
667b496a
PS
36 global $CFG;
37
35b9a80a 38 return new external_function_parameters(
39 array(
40 'users' => new external_multiple_structure(
41 new external_single_structure(
42 array(
7b472b32 43 'username' => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config'),
667b496a 44 'password' => new external_value(PARAM_RAW, 'Plain text password consisting of any characters'),
7b472b32
PS
45 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user'),
46 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user'),
47 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address'),
667b496a 48 'auth' => new external_value(PARAM_SAFEDIR, 'Auth plugins include manual, ldap, imap, etc', false, 'manual', false),
7b472b32
PS
49 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', false),
50 'emailstop' => new external_value(PARAM_NUMBER, 'Email is blocked: 1 is blocked and 0 otherwise', false),
667b496a 51 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en_utf8", must exist on server', false, $CFG->lang, false),
7b472b32
PS
52 'theme' => new external_value(PARAM_SAFEDIR, 'Theme name such as "standard", must exist on server', false),
53 'timezone' => new external_value(PARAM_ALPHANUMEXT, 'Timezone code such as Australia/Perth, or 99 for default', false),
54 'mailformat' => new external_value(PARAM_INTEGER, 'Mail format code is 0 for plain text, 1 for HTML etc', false),
35b9a80a 55 'description' => new external_value(PARAM_TEXT, 'User profile description, as HTML', false),
7b472b32
PS
56 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', false),
57 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', false),
35b9a80a 58 'preferences' => new external_multiple_structure(
59 new external_single_structure(
60 array(
7b472b32 61 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the preference'),
35b9a80a 62 'value' => new external_value(PARAM_RAW, 'The value of the preference')
63 )
64 ), 'User preferences', false),
65 'customfields' => new external_multiple_structure(
66 new external_single_structure(
67 array(
7b472b32 68 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'),
35b9a80a 69 'value' => new external_value(PARAM_RAW, 'The value of the custom field')
70 )
71 ), 'User custom fields', false)
72 )
73 )
74 )
75 )
76 );
625f0a24 77 }
78
d4e13355 79 /**
5de592b1 80 * Create one or more users
81 *
71864f15
PS
82 * @param array $users An array of users to create.
83 * @return array An array of arrays
5de592b1 84 */
7b472b32 85 public static function create_users($users) {
ef22c1b6 86 global $CFG, $DB;
7b472b32 87
5de592b1 88 // Ensure the current user is allowed to run this function
ef22c1b6 89 $context = get_context_instance(CONTEXT_SYSTEM);
5de592b1 90 require_capability('moodle/user:create', $context);
ef22c1b6 91 self::validate_context($context);
92
5de592b1 93 // Do basic automatic PARAM checks on incoming data, using params description
5de592b1 94 // If any problems are found then exceptions are thrown with helpful error messages
7b472b32
PS
95 $params = self::validate_parameters(self::create_users_parameters(), array('users'=>$users));
96
667b496a
PS
97 $availableauths = get_plugin_list('auth');
98 unset($availableauths['mnet']); // these would need mnethostid too
99 unset($availableauths['webservice']); // we do not want new webservice users for now
100
101 $availablethemes = get_plugin_list('theme');
102 $availablelangs = get_list_of_languages();
5de592b1 103
38b76f3c 104 $transaction = $DB->start_delegated_transaction();
5de592b1 105
ef22c1b6 106 $users = array();
7b472b32 107 foreach ($params['users'] as $user) {
667b496a
PS
108 // Make sure that the username doesn't already exist
109 if ($DB->record_exists('user', array('username'=>$user['username'], 'mnethostid'=>$CFG->mnet_localhost_id))) {
110 throw new invalid_parameter_exception('Username already exists: '.$user['username']);
ef22c1b6 111 }
ef22c1b6 112
667b496a
PS
113 // Make sure auth is valid
114 if (empty($availableauths[$user['auth']])) {
115 throw new invalid_parameter_exception('Invalid authentication type: '.$user['auth']);
ef22c1b6 116 }
117
667b496a
PS
118 // Make sure lang is valid
119 if (empty($availablelangs[$user['lang']])) {
120 throw new invalid_parameter_exception('Invalid language code: '.$user['lang']);
ef22c1b6 121 }
122
667b496a
PS
123 // Make sure lang is valid
124 if (empty($availablethemes[$user['theme']])) {
125 throw new invalid_parameter_exception('Invalid theme: '.$user['theme']);
ef22c1b6 126 }
5de592b1 127
38b76f3c
PS
128 // make sure there is no data loss during truncation
129 $truncated = truncate_userinfo($user);
130 foreach ($truncated as $key=>$value) {
131 if ($truncated[$key] !== $user[$key]) {
132 throw new invalid_parameter_exception('Property: '.$key.' is too long: '.$user[$key]);
133 }
134 }
5de592b1 135
38b76f3c 136 // finally create user and beter fetch from DB
ef22c1b6 137 $record = create_user_record($user['username'], $user['password'], $user['auth']);
38b76f3c 138 $newuser = $DB->get_record('user', array('id'=>$record->id), '*', MUST_EXIST);
ef22c1b6 139
38b76f3c 140 // remove already used data
667b496a
PS
141 unset($user['username']);
142 unset($user['password']);
143 unset($user['auth']);
144
38b76f3c 145 // update using given data
667b496a
PS
146 foreach ($user as $key=>$value) {
147 if (is_null($value)) {
148 //ignore missing fields
149 continue;
150 }
38b76f3c
PS
151 if (!array_key_exists($key, $newuser)) {
152 // set only existing
153 continue;
154 }
155 $newuser->$key = $value;
667b496a 156 }
38b76f3c 157 $DB->update_record('user', $newuser);
667b496a 158
d4e13355 159 //TODO: preferences and custom fields
160
38b76f3c 161 $users[] = array('id'=>$newuser->id, 'username'=>$newuser->username);
ef22c1b6 162 }
163
38b76f3c 164 $transaction->allow_commit();
667b496a 165
7b472b32 166 return $users;
ef22c1b6 167 }
168
7b472b32
PS
169 /**
170 * Returns description of method result value
171 * @return external_description
172 */
173 public static function create_users_returns() {
174 return new external_multiple_structure(
175 new external_single_structure(
176 array(
177 'id' => new external_value(PARAM_INT, 'user id'),
178 'username' => new external_value(PARAM_RAW, 'user name'),
179 )
180 )
181 );
d4e13355 182 }
183
184
930680cb
PS
185 /**
186 * Returns description of method parameters
187 * @return external_function_parameters
188 */
d4e13355 189 public static function delete_users_parameters() {
930680cb
PS
190 return new external_function_parameters(
191 array(
192 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user ID')),
193 )
194 );
d4e13355 195 }
930680cb 196
38b76f3c
PS
197 public static function delete_users($userids) {
198 global $CFG, $DB;
199
200 // Ensure the current user is allowed to run this function
201 $context = get_context_instance(CONTEXT_SYSTEM);
202 require_capability('moodle/user:delete', $context);
203 self::validate_context($context);
204
205 $params = self::validate_parameters(self::delete_users_parameters(), array('useids'=>$userids));
206
207 $transaction = $DB->start_delegated_transaction();
47c27706 208// TODO: this is problematic because the DB rollback does not handle rollbacking of deleted user images!
38b76f3c
PS
209
210 foreach ($params['userids'] as $userid) {
211 $user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0), '*', MUST_EXIST);
212 delete_user($user);
213 }
214
215 $transaction->allow_commit();
216
217 return null;
ef22c1b6 218 }
930680cb
PS
219
220 /**
221 * Returns description of method result value
222 * @return external_description
223 */
d4e13355 224 public static function delete_users_returns() {
930680cb 225 return null;
d4e13355 226 }
ef22c1b6 227
228
930680cb
PS
229 /**
230 * Returns description of method parameters
231 * @return external_function_parameters
232 */
d4e13355 233 public static function update_users_parameters() {
234 //TODO
235 }
38b76f3c
PS
236
237 public static function update_users($users) {
238 global $CFG, $DB;
239
240 // Ensure the current user is allowed to run this function
241 $context = get_context_instance(CONTEXT_SYSTEM);
242 require_capability('moodle/user:update', $context);
243 self::validate_context($context);
244
245 $params = self::validate_parameters(self::update_users_parameters(), array('users'=>$users));
246
247 $transaction = $DB->start_delegated_transaction();
248
249 foreach ($params['users'] as $user) {
250 //TODO
251 }
252
253 $transaction->allow_commit();
254
255 return null;
ef22c1b6 256 }
930680cb
PS
257
258 /**
259 * Returns description of method result value
260 * @return external_description
261 */
d4e13355 262 public static function update_users_returns() {
930680cb 263 return null;
d4e13355 264 }
265
7b472b32
PS
266 /**
267 * Returns description of method parameters
268 * @return external_function_parameters
269 */
d4e13355 270 public static function get_users_parameters() {
71864f15
PS
271 return new external_function_parameters(
272 array(
273 'userids' => new external_multiple_structure(new external_value(PARAM_INT, 'user ID')),
274 )
275 );
d4e13355 276 }
7b472b32 277
930680cb 278
71864f15
PS
279 /**
280 * Get user information
281 *
282 * @param array $userids array of user ids
283 * @return array An array of arrays describing users
284 */
285 public static function get_users($userids) {
5de592b1 286 $context = get_context_instance(CONTEXT_SYSTEM);
287 require_capability('moodle/user:viewdetails', $context);
288 self::validate_context($context);
289
71864f15 290 $params = self::validate_parameters(self::get_users_parameters(), array('userids'=>$userids));
5de592b1 291
292 //TODO: this search is probably useless for external systems because it is not exact
293 // 1/ we should specify multiple search parameters including the mnet host id
d4e13355 294
295 $result = array();
71864f15 296/*
d4e13355 297 $users = get_users(true, $params['search'], false, null, 'firstname ASC','', '', '', 1000, 'id, mnethostid, auth, confirmed, username, idnumber, firstname, lastname, email, emailstop, lang, theme, timezone, mailformat, city, description, country');
298 foreach ($users as $user) {
299 $result[] = (array)$user;
71864f15
PS
300 }*/
301
302 return $result;
d4e13355 303 }
7b472b32
PS
304
305 /**
306 * Returns description of method result value
307 * @return external_description
308 */
d4e13355 309 public static function get_users_returns() {
71864f15
PS
310 return new external_multiple_structure(
311 new external_single_structure(
312 array(
313 'username' => new external_value(PARAM_RAW, 'Username policy is defined in Moodle security config'),
314 'firstname' => new external_value(PARAM_NOTAGS, 'The first name(s) of the user'),
315 'lastname' => new external_value(PARAM_NOTAGS, 'The family name of the user'),
316 'email' => new external_value(PARAM_EMAIL, 'A valid and unique email address'),
317 'auth' => new external_value(PARAM_SAFEDIR, 'Auth plugins include manual, ldap, imap, etc', false),
318 'confirmed' => new external_value(PARAM_NUMBER, 'Active user: 1 if confirmed, 0 otherwise', false),
319 'idnumber' => new external_value(PARAM_RAW, 'An arbitrary ID code number perhaps from the institution', false),
320 'emailstop' => new external_value(PARAM_NUMBER, 'Email is blocked: 1 is blocked and 0 otherwise', false),
321 'lang' => new external_value(PARAM_SAFEDIR, 'Language code such as "en_utf8", must exist on server', false),
322 'theme' => new external_value(PARAM_SAFEDIR, 'Theme name such as "standard", must exist on server', false),
323 'timezone' => new external_value(PARAM_ALPHANUMEXT, 'Timezone code such as Australia/Perth, or 99 for default', false),
324 'mailformat' => new external_value(PARAM_INTEGER, 'Mail format code is 0 for plain text, 1 for HTML etc', false),
325 'description' => new external_value(PARAM_TEXT, 'User profile description, as HTML', false),
326 'city' => new external_value(PARAM_NOTAGS, 'Home city of the user', false),
327 'country' => new external_value(PARAM_ALPHA, 'Home country code of the user, such as AU or CZ', false),
328 'customfields' => new external_multiple_structure(
329 new external_single_structure(
330 array(
331 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'),
332 'value' => new external_value(PARAM_RAW, 'The value of the custom field')
333 )
334 ), 'User custom fields', false)
335 )
336 )
337 );
5de592b1 338 }
5de592b1 339}