See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * External user API 19 * 20 * @package core_user 21 * @category external 22 * @copyright 2009 Petr Skodak 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 require_once("$CFG->libdir/externallib.php"); 28 29 /** 30 * User external functions 31 * 32 * @package core_user 33 * @category external 34 * @copyright 2011 Jerome Mouneyrac 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 * @since Moodle 2.2 37 */ 38 class core_user_external extends external_api { 39 40 /** 41 * Returns description of method parameters 42 * 43 * @return external_function_parameters 44 * @since Moodle 2.2 45 */ 46 public static function create_users_parameters() { 47 global $CFG; 48 $userfields = [ 49 'createpassword' => new external_value(PARAM_BOOL, 'True if password should be created and mailed to user.', 50 VALUE_OPTIONAL), 51 // General. 52 'username' => new external_value(core_user::get_property_type('username'), 53 'Username policy is defined in Moodle security config.'), 54 'auth' => new external_value(core_user::get_property_type('auth'), 'Auth plugins include manual, ldap, etc', 55 VALUE_DEFAULT, 'manual', core_user::get_property_null('auth')), 56 'password' => new external_value(core_user::get_property_type('password'), 57 'Plain text password consisting of any characters', VALUE_OPTIONAL), 58 'firstname' => new external_value(core_user::get_property_type('firstname'), 'The first name(s) of the user'), 59 'lastname' => new external_value(core_user::get_property_type('lastname'), 'The family name of the user'), 60 'email' => new external_value(core_user::get_property_type('email'), 'A valid and unique email address'), 61 'maildisplay' => new external_value(core_user::get_property_type('maildisplay'), 'Email visibility', VALUE_OPTIONAL), 62 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user', VALUE_OPTIONAL), 63 'country' => new external_value(core_user::get_property_type('country'), 64 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), 65 'timezone' => new external_value(core_user::get_property_type('timezone'), 66 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), 67 'description' => new external_value(core_user::get_property_type('description'), 'User profile description, no HTML', 68 VALUE_OPTIONAL), 69 // Additional names. 70 'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'), 71 'The first name(s) phonetically of the user', VALUE_OPTIONAL), 72 'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'), 73 'The family name phonetically of the user', VALUE_OPTIONAL), 74 'middlename' => new external_value(core_user::get_property_type('middlename'), 'The middle name of the user', 75 VALUE_OPTIONAL), 76 'alternatename' => new external_value(core_user::get_property_type('alternatename'), 'The alternate name of the user', 77 VALUE_OPTIONAL), 78 // Interests. 79 'interests' => new external_value(PARAM_TEXT, 'User interests (separated by commas)', VALUE_OPTIONAL), 80 // Optional. 81 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 82 'An arbitrary ID code number perhaps from the institution', VALUE_DEFAULT, ''), 83 'institution' => new external_value(core_user::get_property_type('institution'), 'institution', VALUE_OPTIONAL), 84 'department' => new external_value(core_user::get_property_type('department'), 'department', VALUE_OPTIONAL), 85 'phone1' => new external_value(core_user::get_property_type('phone1'), 'Phone 1', VALUE_OPTIONAL), 86 'phone2' => new external_value(core_user::get_property_type('phone2'), 'Phone 2', VALUE_OPTIONAL), 87 'address' => new external_value(core_user::get_property_type('address'), 'Postal address', VALUE_OPTIONAL), 88 // Other user preferences stored in the user table. 89 'lang' => new external_value(core_user::get_property_type('lang'), 'Language code such as "en", must exist on server', 90 VALUE_DEFAULT, core_user::get_property_default('lang'), core_user::get_property_null('lang')), 91 'calendartype' => new external_value(core_user::get_property_type('calendartype'), 92 'Calendar type such as "gregorian", must exist on server', VALUE_DEFAULT, $CFG->calendartype, VALUE_OPTIONAL), 93 'theme' => new external_value(core_user::get_property_type('theme'), 94 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), 95 'mailformat' => new external_value(core_user::get_property_type('mailformat'), 96 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), 97 // Custom user profile fields. 98 'customfields' => new external_multiple_structure( 99 new external_single_structure( 100 [ 101 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'), 102 'value' => new external_value(PARAM_RAW, 'The value of the custom field') 103 ] 104 ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL), 105 // User preferences. 106 'preferences' => new external_multiple_structure( 107 new external_single_structure( 108 [ 109 'type' => new external_value(PARAM_RAW, 'The name of the preference'), 110 'value' => new external_value(PARAM_RAW, 'The value of the preference') 111 ] 112 ), 'User preferences', VALUE_OPTIONAL), 113 ]; 114 return new external_function_parameters( 115 [ 116 'users' => new external_multiple_structure( 117 new external_single_structure($userfields) 118 ) 119 ] 120 ); 121 } 122 123 /** 124 * Create one or more users. 125 * 126 * @throws invalid_parameter_exception 127 * @param array $users An array of users to create. 128 * @return array An array of arrays 129 * @since Moodle 2.2 130 */ 131 public static function create_users($users) { 132 global $CFG, $DB; 133 require_once($CFG->dirroot."/lib/weblib.php"); 134 require_once($CFG->dirroot."/user/lib.php"); 135 require_once($CFG->dirroot."/user/editlib.php"); 136 require_once($CFG->dirroot."/user/profile/lib.php"); // Required for customfields related function. 137 138 // Ensure the current user is allowed to run this function. 139 $context = context_system::instance(); 140 self::validate_context($context); 141 require_capability('moodle/user:create', $context); 142 143 // Do basic automatic PARAM checks on incoming data, using params description. 144 // If any problems are found then exceptions are thrown with helpful error messages. 145 $params = self::validate_parameters(self::create_users_parameters(), array('users' => $users)); 146 147 $availableauths = core_component::get_plugin_list('auth'); 148 unset($availableauths['mnet']); // These would need mnethostid too. 149 unset($availableauths['webservice']); // We do not want new webservice users for now. 150 151 $availablethemes = core_component::get_plugin_list('theme'); 152 $availablelangs = get_string_manager()->get_list_of_translations(); 153 154 $transaction = $DB->start_delegated_transaction(); 155 156 $userids = array(); 157 foreach ($params['users'] as $user) { 158 // Make sure that the username, firstname and lastname are not blank. 159 foreach (array('username', 'firstname', 'lastname') as $fieldname) { 160 if (trim($user[$fieldname]) === '') { 161 throw new invalid_parameter_exception('The field '.$fieldname.' cannot be blank'); 162 } 163 } 164 165 // Make sure that the username doesn't already exist. 166 if ($DB->record_exists('user', array('username' => $user['username'], 'mnethostid' => $CFG->mnet_localhost_id))) { 167 throw new invalid_parameter_exception('Username already exists: '.$user['username']); 168 } 169 170 // Make sure auth is valid. 171 if (empty($availableauths[$user['auth']])) { 172 throw new invalid_parameter_exception('Invalid authentication type: '.$user['auth']); 173 } 174 175 // Make sure lang is valid. 176 if (empty($availablelangs[$user['lang']])) { 177 throw new invalid_parameter_exception('Invalid language code: '.$user['lang']); 178 } 179 180 // Make sure lang is valid. 181 if (!empty($user['theme']) && empty($availablethemes[$user['theme']])) { // Theme is VALUE_OPTIONAL, 182 // so no default value 183 // We need to test if the client sent it 184 // => !empty($user['theme']). 185 throw new invalid_parameter_exception('Invalid theme: '.$user['theme']); 186 } 187 188 // Make sure we have a password or have to create one. 189 $authplugin = get_auth_plugin($user['auth']); 190 if ($authplugin->is_internal() && empty($user['password']) && empty($user['createpassword'])) { 191 throw new invalid_parameter_exception('Invalid password: you must provide a password, or set createpassword.'); 192 } 193 194 $user['confirmed'] = true; 195 $user['mnethostid'] = $CFG->mnet_localhost_id; 196 197 // Start of user info validation. 198 // Make sure we validate current user info as handled by current GUI. See user/editadvanced_form.php func validation(). 199 if (!validate_email($user['email'])) { 200 throw new invalid_parameter_exception('Email address is invalid: '.$user['email']); 201 } else if (empty($CFG->allowaccountssameemail)) { 202 // Make a case-insensitive query for the given email address. 203 $select = $DB->sql_equal('email', ':email', false) . ' AND mnethostid = :mnethostid'; 204 $params = array( 205 'email' => $user['email'], 206 'mnethostid' => $user['mnethostid'] 207 ); 208 // If there are other user(s) that already have the same email, throw an error. 209 if ($DB->record_exists_select('user', $select, $params)) { 210 throw new invalid_parameter_exception('Email address already exists: '.$user['email']); 211 } 212 } 213 // End of user info validation. 214 215 $createpassword = !empty($user['createpassword']); 216 unset($user['createpassword']); 217 $updatepassword = false; 218 if ($authplugin->is_internal()) { 219 if ($createpassword) { 220 $user['password'] = ''; 221 } else { 222 $updatepassword = true; 223 } 224 } else { 225 $user['password'] = AUTH_PASSWORD_NOT_CACHED; 226 } 227 228 // Create the user data now! 229 $user['id'] = user_create_user($user, $updatepassword, false); 230 231 $userobject = (object)$user; 232 233 // Set user interests. 234 if (!empty($user['interests'])) { 235 $trimmedinterests = array_map('trim', explode(',', $user['interests'])); 236 $interests = array_filter($trimmedinterests, function($value) { 237 return !empty($value); 238 }); 239 useredit_update_interests($userobject, $interests); 240 } 241 242 // Custom fields. 243 if (!empty($user['customfields'])) { 244 foreach ($user['customfields'] as $customfield) { 245 // Profile_save_data() saves profile file it's expecting a user with the correct id, 246 // and custom field to be named profile_field_"shortname". 247 $user["profile_field_".$customfield['type']] = $customfield['value']; 248 } 249 profile_save_data((object) $user); 250 } 251 252 if ($createpassword) { 253 setnew_password_and_mail($userobject); 254 unset_user_preference('create_password', $userobject); 255 set_user_preference('auth_forcepasswordchange', 1, $userobject); 256 } 257 258 // Trigger event. 259 \core\event\user_created::create_from_userid($user['id'])->trigger(); 260 261 // Preferences. 262 if (!empty($user['preferences'])) { 263 $userpref = (object)$user; 264 foreach ($user['preferences'] as $preference) { 265 $userpref->{'preference_'.$preference['type']} = $preference['value']; 266 } 267 useredit_update_user_preference($userpref); 268 } 269 270 $userids[] = array('id' => $user['id'], 'username' => $user['username']); 271 } 272 273 $transaction->allow_commit(); 274 275 return $userids; 276 } 277 278 /** 279 * Returns description of method result value 280 * 281 * @return external_description 282 * @since Moodle 2.2 283 */ 284 public static function create_users_returns() { 285 return new external_multiple_structure( 286 new external_single_structure( 287 array( 288 'id' => new external_value(core_user::get_property_type('id'), 'user id'), 289 'username' => new external_value(core_user::get_property_type('username'), 'user name'), 290 ) 291 ) 292 ); 293 } 294 295 296 /** 297 * Returns description of method parameters 298 * 299 * @return external_function_parameters 300 * @since Moodle 2.2 301 */ 302 public static function delete_users_parameters() { 303 return new external_function_parameters( 304 array( 305 'userids' => new external_multiple_structure(new external_value(core_user::get_property_type('id'), 'user ID')), 306 ) 307 ); 308 } 309 310 /** 311 * Delete users 312 * 313 * @throws moodle_exception 314 * @param array $userids 315 * @return null 316 * @since Moodle 2.2 317 */ 318 public static function delete_users($userids) { 319 global $CFG, $DB, $USER; 320 require_once($CFG->dirroot."/user/lib.php"); 321 322 // Ensure the current user is allowed to run this function. 323 $context = context_system::instance(); 324 require_capability('moodle/user:delete', $context); 325 self::validate_context($context); 326 327 $params = self::validate_parameters(self::delete_users_parameters(), array('userids' => $userids)); 328 329 $transaction = $DB->start_delegated_transaction(); 330 331 foreach ($params['userids'] as $userid) { 332 $user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0), '*', MUST_EXIST); 333 // Must not allow deleting of admins or self!!! 334 if (is_siteadmin($user)) { 335 throw new moodle_exception('useradminodelete', 'error'); 336 } 337 if ($USER->id == $user->id) { 338 throw new moodle_exception('usernotdeletederror', 'error'); 339 } 340 user_delete_user($user); 341 } 342 343 $transaction->allow_commit(); 344 345 return null; 346 } 347 348 /** 349 * Returns description of method result value 350 * 351 * @return null 352 * @since Moodle 2.2 353 */ 354 public static function delete_users_returns() { 355 return null; 356 } 357 358 /** 359 * Returns description of method parameters. 360 * 361 * @return external_function_parameters 362 * @since Moodle 3.2 363 */ 364 public static function update_user_preferences_parameters() { 365 return new external_function_parameters( 366 array( 367 'userid' => new external_value(PARAM_INT, 'id of the user, default to current user', VALUE_DEFAULT, 0), 368 'emailstop' => new external_value(core_user::get_property_type('emailstop'), 369 'Enable or disable notifications for this user', VALUE_DEFAULT, null), 370 'preferences' => new external_multiple_structure( 371 new external_single_structure( 372 array( 373 'type' => new external_value(PARAM_RAW, 'The name of the preference'), 374 'value' => new external_value(PARAM_RAW, 'The value of the preference, do not set this field if you 375 want to remove (unset) the current value.', VALUE_DEFAULT, null), 376 ) 377 ), 'User preferences', VALUE_DEFAULT, array() 378 ) 379 ) 380 ); 381 } 382 383 /** 384 * Update the user's preferences. 385 * 386 * @param int $userid 387 * @param bool|null $emailstop 388 * @param array $preferences 389 * @return null 390 * @since Moodle 3.2 391 */ 392 public static function update_user_preferences($userid = 0, $emailstop = null, $preferences = array()) { 393 global $USER, $CFG; 394 395 require_once($CFG->dirroot . '/user/lib.php'); 396 require_once($CFG->dirroot . '/user/editlib.php'); 397 require_once($CFG->dirroot . '/message/lib.php'); 398 399 if (empty($userid)) { 400 $userid = $USER->id; 401 } 402 403 $systemcontext = context_system::instance(); 404 self::validate_context($systemcontext); 405 $params = array( 406 'userid' => $userid, 407 'emailstop' => $emailstop, 408 'preferences' => $preferences 409 ); 410 $params = self::validate_parameters(self::update_user_preferences_parameters(), $params); 411 $preferences = $params['preferences']; 412 413 // Preferences. 414 if (!empty($preferences)) { 415 $userpref = ['id' => $userid]; 416 foreach ($preferences as $preference) { 417 418 /* 419 * Rename user message provider preferences to avoid orphan settings on old app versions. 420 * @todo Remove this "translation" block on MDL-73284. 421 */ 422 if (preg_match('/message_provider_.*_loggedin/', $preference['type']) || 423 preg_match('/message_provider_.*_loggedoff/', $preference['type'])) { 424 $nameparts = explode('_', $preference['type']); 425 array_pop($nameparts); 426 $preference['type'] = implode('_', $nameparts).'_enabled'; 427 } 428 429 $userpref['preference_' . $preference['type']] = $preference['value']; 430 } 431 useredit_update_user_preference($userpref); 432 } 433 434 // Check if they want to update the email. 435 if ($emailstop !== null) { 436 $otheruser = ($userid == $USER->id) ? $USER : core_user::get_user($userid, '*', MUST_EXIST); 437 core_user::require_active_user($otheruser); 438 if (core_message_can_edit_message_profile($otheruser) && $otheruser->emailstop != $emailstop) { 439 $user = new stdClass(); 440 $user->id = $userid; 441 $user->emailstop = $emailstop; 442 user_update_user($user); 443 444 // Update the $USER if we should. 445 if ($userid == $USER->id) { 446 $USER->emailstop = $emailstop; 447 } 448 } 449 } 450 451 return null; 452 } 453 454 /** 455 * Returns description of method result value 456 * 457 * @return null 458 * @since Moodle 3.2 459 */ 460 public static function update_user_preferences_returns() { 461 return null; 462 } 463 464 /** 465 * Returns description of method parameters 466 * 467 * @return external_function_parameters 468 * @since Moodle 2.2 469 */ 470 public static function update_users_parameters() { 471 $userfields = [ 472 'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'), 473 // General. 474 'username' => new external_value(core_user::get_property_type('username'), 475 'Username policy is defined in Moodle security config.', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 476 'auth' => new external_value(core_user::get_property_type('auth'), 'Auth plugins include manual, ldap, etc', 477 VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 478 'suspended' => new external_value(core_user::get_property_type('suspended'), 479 'Suspend user account, either false to enable user login or true to disable it', VALUE_OPTIONAL), 480 'password' => new external_value(core_user::get_property_type('password'), 481 'Plain text password consisting of any characters', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 482 'firstname' => new external_value(core_user::get_property_type('firstname'), 'The first name(s) of the user', 483 VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 484 'lastname' => new external_value(core_user::get_property_type('lastname'), 'The family name of the user', 485 VALUE_OPTIONAL), 486 'email' => new external_value(core_user::get_property_type('email'), 'A valid and unique email address', VALUE_OPTIONAL, 487 '', NULL_NOT_ALLOWED), 488 'maildisplay' => new external_value(core_user::get_property_type('maildisplay'), 'Email visibility', VALUE_OPTIONAL), 489 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user', VALUE_OPTIONAL), 490 'country' => new external_value(core_user::get_property_type('country'), 491 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), 492 'timezone' => new external_value(core_user::get_property_type('timezone'), 493 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), 494 'description' => new external_value(core_user::get_property_type('description'), 'User profile description, no HTML', 495 VALUE_OPTIONAL), 496 // User picture. 497 'userpicture' => new external_value(PARAM_INT, 498 'The itemid where the new user picture has been uploaded to, 0 to delete', VALUE_OPTIONAL), 499 // Additional names. 500 'firstnamephonetic' => new external_value(core_user::get_property_type('firstnamephonetic'), 501 'The first name(s) phonetically of the user', VALUE_OPTIONAL), 502 'lastnamephonetic' => new external_value(core_user::get_property_type('lastnamephonetic'), 503 'The family name phonetically of the user', VALUE_OPTIONAL), 504 'middlename' => new external_value(core_user::get_property_type('middlename'), 'The middle name of the user', 505 VALUE_OPTIONAL), 506 'alternatename' => new external_value(core_user::get_property_type('alternatename'), 'The alternate name of the user', 507 VALUE_OPTIONAL), 508 // Interests. 509 'interests' => new external_value(PARAM_TEXT, 'User interests (separated by commas)', VALUE_OPTIONAL), 510 // Optional. 511 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 512 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), 513 'institution' => new external_value(core_user::get_property_type('institution'), 'Institution', VALUE_OPTIONAL), 514 'department' => new external_value(core_user::get_property_type('department'), 'Department', VALUE_OPTIONAL), 515 'phone1' => new external_value(core_user::get_property_type('phone1'), 'Phone', VALUE_OPTIONAL), 516 'phone2' => new external_value(core_user::get_property_type('phone2'), 'Mobile phone', VALUE_OPTIONAL), 517 'address' => new external_value(core_user::get_property_type('address'), 'Postal address', VALUE_OPTIONAL), 518 // Other user preferences stored in the user table. 519 'lang' => new external_value(core_user::get_property_type('lang'), 'Language code such as "en", must exist on server', 520 VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 521 'calendartype' => new external_value(core_user::get_property_type('calendartype'), 522 'Calendar type such as "gregorian", must exist on server', VALUE_OPTIONAL, '', NULL_NOT_ALLOWED), 523 'theme' => new external_value(core_user::get_property_type('theme'), 524 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), 525 'mailformat' => new external_value(core_user::get_property_type('mailformat'), 526 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), 527 // Custom user profile fields. 528 'customfields' => new external_multiple_structure( 529 new external_single_structure( 530 [ 531 'type' => new external_value(PARAM_ALPHANUMEXT, 'The name of the custom field'), 532 'value' => new external_value(PARAM_RAW, 'The value of the custom field') 533 ] 534 ), 'User custom fields (also known as user profil fields)', VALUE_OPTIONAL), 535 // User preferences. 536 'preferences' => new external_multiple_structure( 537 new external_single_structure( 538 [ 539 'type' => new external_value(PARAM_RAW, 'The name of the preference'), 540 'value' => new external_value(PARAM_RAW, 'The value of the preference') 541 ] 542 ), 'User preferences', VALUE_OPTIONAL), 543 ]; 544 return new external_function_parameters( 545 [ 546 'users' => new external_multiple_structure( 547 new external_single_structure($userfields) 548 ) 549 ] 550 ); 551 } 552 553 /** 554 * Update users 555 * 556 * @param array $users 557 * @return null 558 * @since Moodle 2.2 559 */ 560 public static function update_users($users) { 561 global $CFG, $DB, $USER; 562 require_once($CFG->dirroot."/user/lib.php"); 563 require_once($CFG->dirroot."/user/profile/lib.php"); // Required for customfields related function. 564 require_once($CFG->dirroot.'/user/editlib.php'); 565 566 // Ensure the current user is allowed to run this function. 567 $context = context_system::instance(); 568 require_capability('moodle/user:update', $context); 569 self::validate_context($context); 570 571 $params = self::validate_parameters(self::update_users_parameters(), array('users' => $users)); 572 573 $filemanageroptions = array('maxbytes' => $CFG->maxbytes, 574 'subdirs' => 0, 575 'maxfiles' => 1, 576 'accepted_types' => 'optimised_image'); 577 578 $warnings = array(); 579 foreach ($params['users'] as $user) { 580 // Catch any exception while updating a user and return it as a warning. 581 try { 582 $transaction = $DB->start_delegated_transaction(); 583 584 // First check the user exists. 585 if (!$existinguser = core_user::get_user($user['id'])) { 586 throw new moodle_exception('invaliduserid', '', '', null, 587 'Invalid user ID'); 588 } 589 // Check if we are trying to update an admin. 590 if ($existinguser->id != $USER->id and is_siteadmin($existinguser) and !is_siteadmin($USER)) { 591 throw new moodle_exception('usernotupdatedadmin', '', '', null, 592 'Cannot update admin accounts'); 593 } 594 // Other checks (deleted, remote or guest users). 595 if ($existinguser->deleted) { 596 throw new moodle_exception('usernotupdateddeleted', '', '', null, 597 'User is a deleted user'); 598 } 599 if (is_mnet_remote_user($existinguser)) { 600 throw new moodle_exception('usernotupdatedremote', '', '', null, 601 'User is a remote user'); 602 } 603 if (isguestuser($existinguser->id)) { 604 throw new moodle_exception('usernotupdatedguest', '', '', null, 605 'Cannot update guest account'); 606 } 607 // Check duplicated emails. 608 if (isset($user['email']) && $user['email'] !== $existinguser->email) { 609 if (!validate_email($user['email'])) { 610 throw new moodle_exception('useremailinvalid', '', '', null, 611 'Invalid email address'); 612 } else if (empty($CFG->allowaccountssameemail)) { 613 // Make a case-insensitive query for the given email address 614 // and make sure to exclude the user being updated. 615 $select = $DB->sql_equal('email', ':email', false) . ' AND mnethostid = :mnethostid AND id <> :userid'; 616 $params = array( 617 'email' => $user['email'], 618 'mnethostid' => $CFG->mnet_localhost_id, 619 'userid' => $user['id'] 620 ); 621 // Skip if there are other user(s) that already have the same email. 622 if ($DB->record_exists_select('user', $select, $params)) { 623 throw new moodle_exception('useremailduplicate', '', '', null, 624 'Duplicate email address'); 625 } 626 } 627 } 628 629 user_update_user($user, true, false); 630 631 $userobject = (object)$user; 632 633 // Update user picture if it was specified for this user. 634 if (empty($CFG->disableuserimages) && isset($user['userpicture'])) { 635 $userobject->deletepicture = null; 636 637 if ($user['userpicture'] == 0) { 638 $userobject->deletepicture = true; 639 } else { 640 $userobject->imagefile = $user['userpicture']; 641 } 642 643 core_user::update_picture($userobject, $filemanageroptions); 644 } 645 646 // Update user interests. 647 if (!empty($user['interests'])) { 648 $trimmedinterests = array_map('trim', explode(',', $user['interests'])); 649 $interests = array_filter($trimmedinterests, function($value) { 650 return !empty($value); 651 }); 652 useredit_update_interests($userobject, $interests); 653 } 654 655 // Update user custom fields. 656 if (!empty($user['customfields'])) { 657 658 foreach ($user['customfields'] as $customfield) { 659 // Profile_save_data() saves profile file it's expecting a user with the correct id, 660 // and custom field to be named profile_field_"shortname". 661 $user["profile_field_".$customfield['type']] = $customfield['value']; 662 } 663 profile_save_data((object) $user); 664 } 665 666 // Trigger event. 667 \core\event\user_updated::create_from_userid($user['id'])->trigger(); 668 669 // Preferences. 670 if (!empty($user['preferences'])) { 671 $userpref = clone($existinguser); 672 foreach ($user['preferences'] as $preference) { 673 $userpref->{'preference_'.$preference['type']} = $preference['value']; 674 } 675 useredit_update_user_preference($userpref); 676 } 677 if (isset($user['suspended']) and $user['suspended']) { 678 \core\session\manager::kill_user_sessions($user['id']); 679 } 680 681 $transaction->allow_commit(); 682 } catch (Exception $e) { 683 try { 684 $transaction->rollback($e); 685 } catch (Exception $e) { 686 $warning = []; 687 $warning['item'] = 'user'; 688 $warning['itemid'] = $user['id']; 689 if ($e instanceof moodle_exception) { 690 $warning['warningcode'] = $e->errorcode; 691 } else { 692 $warning['warningcode'] = $e->getCode(); 693 } 694 $warning['message'] = $e->getMessage(); 695 $warnings[] = $warning; 696 } 697 } 698 } 699 700 return ['warnings' => $warnings]; 701 } 702 703 /** 704 * Returns description of method result value 705 * 706 * @return external_description 707 * @since Moodle 2.2 708 */ 709 public static function update_users_returns() { 710 return new external_single_structure( 711 array( 712 'warnings' => new external_warnings() 713 ) 714 ); 715 } 716 717 /** 718 * Returns description of method parameters 719 * 720 * @return external_function_parameters 721 * @since Moodle 2.4 722 */ 723 public static function get_users_by_field_parameters() { 724 return new external_function_parameters( 725 array( 726 'field' => new external_value(PARAM_ALPHA, 'the search field can be 727 \'id\' or \'idnumber\' or \'username\' or \'email\''), 728 'values' => new external_multiple_structure( 729 new external_value(PARAM_RAW, 'the value to match')) 730 ) 731 ); 732 } 733 734 /** 735 * Get user information for a unique field. 736 * 737 * @throws coding_exception 738 * @throws invalid_parameter_exception 739 * @param string $field 740 * @param array $values 741 * @return array An array of arrays containg user profiles. 742 * @since Moodle 2.4 743 */ 744 public static function get_users_by_field($field, $values) { 745 global $CFG, $USER, $DB; 746 require_once($CFG->dirroot . "/user/lib.php"); 747 748 $params = self::validate_parameters(self::get_users_by_field_parameters(), 749 array('field' => $field, 'values' => $values)); 750 751 // This array will keep all the users that are allowed to be searched, 752 // according to the current user's privileges. 753 $cleanedvalues = array(); 754 755 switch ($field) { 756 case 'id': 757 $paramtype = core_user::get_property_type('id'); 758 break; 759 case 'idnumber': 760 $paramtype = core_user::get_property_type('idnumber'); 761 break; 762 case 'username': 763 $paramtype = core_user::get_property_type('username'); 764 break; 765 case 'email': 766 $paramtype = core_user::get_property_type('email'); 767 break; 768 default: 769 throw new coding_exception('invalid field parameter', 770 'The search field \'' . $field . '\' is not supported, look at the web service documentation'); 771 } 772 773 // Clean the values. 774 foreach ($values as $value) { 775 $cleanedvalue = clean_param($value, $paramtype); 776 if ( $value != $cleanedvalue) { 777 throw new invalid_parameter_exception('The field \'' . $field . 778 '\' value is invalid: ' . $value . '(cleaned value: '.$cleanedvalue.')'); 779 } 780 $cleanedvalues[] = $cleanedvalue; 781 } 782 783 // Retrieve the users. 784 $users = $DB->get_records_list('user', $field, $cleanedvalues, 'id'); 785 786 $context = context_system::instance(); 787 self::validate_context($context); 788 789 // Finally retrieve each users information. 790 $returnedusers = array(); 791 foreach ($users as $user) { 792 $userdetails = user_get_user_details_courses($user); 793 794 // Return the user only if the searched field is returned. 795 // Otherwise it means that the $USER was not allowed to search the returned user. 796 if (!empty($userdetails) and !empty($userdetails[$field])) { 797 $returnedusers[] = $userdetails; 798 } 799 } 800 801 return $returnedusers; 802 } 803 804 /** 805 * Returns description of method result value 806 * 807 * @return external_multiple_structure 808 * @since Moodle 2.4 809 */ 810 public static function get_users_by_field_returns() { 811 return new external_multiple_structure(self::user_description()); 812 } 813 814 815 /** 816 * Returns description of get_users() parameters. 817 * 818 * @return external_function_parameters 819 * @since Moodle 2.5 820 */ 821 public static function get_users_parameters() { 822 return new external_function_parameters( 823 array( 824 'criteria' => new external_multiple_structure( 825 new external_single_structure( 826 array( 827 'key' => new external_value(PARAM_ALPHA, 'the user column to search, expected keys (value format) are: 828 "id" (int) matching user id, 829 "lastname" (string) user last name (Note: you can use % for searching but it may be considerably slower!), 830 "firstname" (string) user first name (Note: you can use % for searching but it may be considerably slower!), 831 "idnumber" (string) matching user idnumber, 832 "username" (string) matching user username, 833 "email" (string) user email (Note: you can use % for searching but it may be considerably slower!), 834 "auth" (string) matching user auth plugin'), 835 'value' => new external_value(PARAM_RAW, 'the value to search') 836 ) 837 ), 'the key/value pairs to be considered in user search. Values can not be empty. 838 Specify different keys only once (fullname => \'user1\', auth => \'manual\', ...) - 839 key occurences are forbidden. 840 The search is executed with AND operator on the criterias. Invalid criterias (keys) are ignored, 841 the search is still executed on the valid criterias. 842 You can search without criteria, but the function is not designed for it. 843 It could very slow or timeout. The function is designed to search some specific users.' 844 ) 845 ) 846 ); 847 } 848 849 /** 850 * Retrieve matching user. 851 * 852 * @throws moodle_exception 853 * @param array $criteria the allowed array keys are id/lastname/firstname/idnumber/username/email/auth. 854 * @return array An array of arrays containing user profiles. 855 * @since Moodle 2.5 856 */ 857 public static function get_users($criteria = array()) { 858 global $CFG, $USER, $DB; 859 860 require_once($CFG->dirroot . "/user/lib.php"); 861 862 $params = self::validate_parameters(self::get_users_parameters(), 863 array('criteria' => $criteria)); 864 865 // Validate the criteria and retrieve the users. 866 $users = array(); 867 $warnings = array(); 868 $sqlparams = array(); 869 $usedkeys = array(); 870 871 // Do not retrieve deleted users. 872 $sql = ' deleted = 0'; 873 874 foreach ($params['criteria'] as $criteriaindex => $criteria) { 875 876 // Check that the criteria has never been used. 877 if (array_key_exists($criteria['key'], $usedkeys)) { 878 throw new moodle_exception('keyalreadyset', '', '', null, 'The key ' . $criteria['key'] . ' can only be sent once'); 879 } else { 880 $usedkeys[$criteria['key']] = true; 881 } 882 883 $invalidcriteria = false; 884 // Clean the parameters. 885 $paramtype = PARAM_RAW; 886 switch ($criteria['key']) { 887 case 'id': 888 $paramtype = core_user::get_property_type('id'); 889 break; 890 case 'idnumber': 891 $paramtype = core_user::get_property_type('idnumber'); 892 break; 893 case 'username': 894 $paramtype = core_user::get_property_type('username'); 895 break; 896 case 'email': 897 // We use PARAM_RAW to allow searches with %. 898 $paramtype = core_user::get_property_type('email'); 899 break; 900 case 'auth': 901 $paramtype = core_user::get_property_type('auth'); 902 break; 903 case 'lastname': 904 case 'firstname': 905 $paramtype = core_user::get_property_type('firstname'); 906 break; 907 default: 908 // Send back a warning that this search key is not supported in this version. 909 // This warning will make the function extandable without breaking clients. 910 $warnings[] = array( 911 'item' => $criteria['key'], 912 'warningcode' => 'invalidfieldparameter', 913 'message' => 914 'The search key \'' . $criteria['key'] . '\' is not supported, look at the web service documentation' 915 ); 916 // Do not add this invalid criteria to the created SQL request. 917 $invalidcriteria = true; 918 unset($params['criteria'][$criteriaindex]); 919 break; 920 } 921 922 if (!$invalidcriteria) { 923 $cleanedvalue = clean_param($criteria['value'], $paramtype); 924 925 $sql .= ' AND '; 926 927 // Create the SQL. 928 switch ($criteria['key']) { 929 case 'id': 930 case 'idnumber': 931 case 'username': 932 case 'auth': 933 $sql .= $criteria['key'] . ' = :' . $criteria['key']; 934 $sqlparams[$criteria['key']] = $cleanedvalue; 935 break; 936 case 'email': 937 case 'lastname': 938 case 'firstname': 939 $sql .= $DB->sql_like($criteria['key'], ':' . $criteria['key'], false); 940 $sqlparams[$criteria['key']] = $cleanedvalue; 941 break; 942 default: 943 break; 944 } 945 } 946 } 947 948 $users = $DB->get_records_select('user', $sql, $sqlparams, 'id ASC'); 949 950 // Finally retrieve each users information. 951 $returnedusers = array(); 952 foreach ($users as $user) { 953 $userdetails = user_get_user_details_courses($user); 954 955 // Return the user only if all the searched fields are returned. 956 // Otherwise it means that the $USER was not allowed to search the returned user. 957 if (!empty($userdetails)) { 958 $validuser = true; 959 960 foreach ($params['criteria'] as $criteria) { 961 if (empty($userdetails[$criteria['key']])) { 962 $validuser = false; 963 } 964 } 965 966 if ($validuser) { 967 $returnedusers[] = $userdetails; 968 } 969 } 970 } 971 972 return array('users' => $returnedusers, 'warnings' => $warnings); 973 } 974 975 /** 976 * Returns description of get_users result value. 977 * 978 * @return external_description 979 * @since Moodle 2.5 980 */ 981 public static function get_users_returns() { 982 return new external_single_structure( 983 array('users' => new external_multiple_structure( 984 self::user_description() 985 ), 986 'warnings' => new external_warnings('always set to \'key\'', 'faulty key name') 987 ) 988 ); 989 } 990 991 /** 992 * Returns description of method parameters 993 * 994 * @return external_function_parameters 995 * @since Moodle 2.2 996 */ 997 public static function get_course_user_profiles_parameters() { 998 return new external_function_parameters( 999 array( 1000 'userlist' => new external_multiple_structure( 1001 new external_single_structure( 1002 array( 1003 'userid' => new external_value(core_user::get_property_type('id'), 'userid'), 1004 'courseid' => new external_value(PARAM_INT, 'courseid'), 1005 ) 1006 ) 1007 ) 1008 ) 1009 ); 1010 } 1011 1012 /** 1013 * Get course participant's details 1014 * 1015 * @param array $userlist array of user ids and according course ids 1016 * @return array An array of arrays describing course participants 1017 * @since Moodle 2.2 1018 */ 1019 public static function get_course_user_profiles($userlist) { 1020 global $CFG, $USER, $DB; 1021 require_once($CFG->dirroot . "/user/lib.php"); 1022 $params = self::validate_parameters(self::get_course_user_profiles_parameters(), array('userlist' => $userlist)); 1023 1024 $userids = array(); 1025 $courseids = array(); 1026 foreach ($params['userlist'] as $value) { 1027 $userids[] = $value['userid']; 1028 $courseids[$value['userid']] = $value['courseid']; 1029 } 1030 1031 // Cache all courses. 1032 $courses = array(); 1033 list($sqlcourseids, $params) = $DB->get_in_or_equal(array_unique($courseids), SQL_PARAMS_NAMED); 1034 $cselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); 1035 $cjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel)"; 1036 $params['contextlevel'] = CONTEXT_COURSE; 1037 $coursesql = "SELECT c.* $cselect 1038 FROM {course} c $cjoin 1039 WHERE c.id $sqlcourseids"; 1040 $rs = $DB->get_recordset_sql($coursesql, $params); 1041 foreach ($rs as $course) { 1042 // Adding course contexts to cache. 1043 context_helper::preload_from_record($course); 1044 // Cache courses. 1045 $courses[$course->id] = $course; 1046 } 1047 $rs->close(); 1048 1049 list($sqluserids, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); 1050 $uselect = ', ' . context_helper::get_preload_record_columns_sql('ctx'); 1051 $ujoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)"; 1052 $params['contextlevel'] = CONTEXT_USER; 1053 $usersql = "SELECT u.* $uselect 1054 FROM {user} u $ujoin 1055 WHERE u.id $sqluserids"; 1056 $users = $DB->get_recordset_sql($usersql, $params); 1057 $result = array(); 1058 foreach ($users as $user) { 1059 if (!empty($user->deleted)) { 1060 continue; 1061 } 1062 context_helper::preload_from_record($user); 1063 $course = $courses[$courseids[$user->id]]; 1064 $context = context_course::instance($courseids[$user->id], IGNORE_MISSING); 1065 self::validate_context($context); 1066 if ($userarray = user_get_user_details($user, $course)) { 1067 $result[] = $userarray; 1068 } 1069 } 1070 1071 $users->close(); 1072 1073 return $result; 1074 } 1075 1076 /** 1077 * Returns description of method result value 1078 * 1079 * @return external_description 1080 * @since Moodle 2.2 1081 */ 1082 public static function get_course_user_profiles_returns() { 1083 $additionalfields = array( 1084 'groups' => new external_multiple_structure( 1085 new external_single_structure( 1086 array( 1087 'id' => new external_value(PARAM_INT, 'group id'), 1088 'name' => new external_value(PARAM_RAW, 'group name'), 1089 'description' => new external_value(PARAM_RAW, 'group description'), 1090 'descriptionformat' => new external_format_value('description'), 1091 ) 1092 ), 'user groups', VALUE_OPTIONAL), 1093 'roles' => new external_multiple_structure( 1094 new external_single_structure( 1095 array( 1096 'roleid' => new external_value(PARAM_INT, 'role id'), 1097 'name' => new external_value(PARAM_RAW, 'role name'), 1098 'shortname' => new external_value(PARAM_ALPHANUMEXT, 'role shortname'), 1099 'sortorder' => new external_value(PARAM_INT, 'role sortorder') 1100 ) 1101 ), 'user roles', VALUE_OPTIONAL), 1102 'enrolledcourses' => new external_multiple_structure( 1103 new external_single_structure( 1104 array( 1105 'id' => new external_value(PARAM_INT, 'Id of the course'), 1106 'fullname' => new external_value(PARAM_RAW, 'Fullname of the course'), 1107 'shortname' => new external_value(PARAM_RAW, 'Shortname of the course') 1108 ) 1109 ), 'Courses where the user is enrolled - limited by which courses the user is able to see', VALUE_OPTIONAL) 1110 ); 1111 1112 return new external_multiple_structure(self::user_description($additionalfields)); 1113 } 1114 1115 /** 1116 * Create user return value description. 1117 * 1118 * @param array $additionalfields some additional field 1119 * @return single_structure_description 1120 */ 1121 public static function user_description($additionalfields = array()) { 1122 $userfields = array( 1123 'id' => new external_value(core_user::get_property_type('id'), 'ID of the user'), 1124 'username' => new external_value(core_user::get_property_type('username'), 'The username', VALUE_OPTIONAL), 1125 'firstname' => new external_value(core_user::get_property_type('firstname'), 'The first name(s) of the user', VALUE_OPTIONAL), 1126 'lastname' => new external_value(core_user::get_property_type('lastname'), 'The family name of the user', VALUE_OPTIONAL), 1127 'fullname' => new external_value(core_user::get_property_type('firstname'), 'The fullname of the user'), 1128 'email' => new external_value(core_user::get_property_type('email'), 'An email address - allow email as root@localhost', VALUE_OPTIONAL), 1129 'address' => new external_value(core_user::get_property_type('address'), 'Postal address', VALUE_OPTIONAL), 1130 'phone1' => new external_value(core_user::get_property_type('phone1'), 'Phone 1', VALUE_OPTIONAL), 1131 'phone2' => new external_value(core_user::get_property_type('phone2'), 'Phone 2', VALUE_OPTIONAL), 1132 'department' => new external_value(core_user::get_property_type('department'), 'department', VALUE_OPTIONAL), 1133 'institution' => new external_value(core_user::get_property_type('institution'), 'institution', VALUE_OPTIONAL), 1134 'idnumber' => new external_value(core_user::get_property_type('idnumber'), 'An arbitrary ID code number perhaps from the institution', VALUE_OPTIONAL), 1135 'interests' => new external_value(PARAM_TEXT, 'user interests (separated by commas)', VALUE_OPTIONAL), 1136 'firstaccess' => new external_value(core_user::get_property_type('firstaccess'), 'first access to the site (0 if never)', VALUE_OPTIONAL), 1137 'lastaccess' => new external_value(core_user::get_property_type('lastaccess'), 'last access to the site (0 if never)', VALUE_OPTIONAL), 1138 'auth' => new external_value(core_user::get_property_type('auth'), 'Auth plugins include manual, ldap, etc', VALUE_OPTIONAL), 1139 'suspended' => new external_value(core_user::get_property_type('suspended'), 'Suspend user account, either false to enable user login or true to disable it', VALUE_OPTIONAL), 1140 'confirmed' => new external_value(core_user::get_property_type('confirmed'), 'Active user: 1 if confirmed, 0 otherwise', VALUE_OPTIONAL), 1141 'lang' => new external_value(core_user::get_property_type('lang'), 'Language code such as "en", must exist on server', VALUE_OPTIONAL), 1142 'calendartype' => new external_value(core_user::get_property_type('calendartype'), 'Calendar type such as "gregorian", must exist on server', VALUE_OPTIONAL), 1143 'theme' => new external_value(core_user::get_property_type('theme'), 'Theme name such as "standard", must exist on server', VALUE_OPTIONAL), 1144 'timezone' => new external_value(core_user::get_property_type('timezone'), 'Timezone code such as Australia/Perth, or 99 for default', VALUE_OPTIONAL), 1145 'mailformat' => new external_value(core_user::get_property_type('mailformat'), 'Mail format code is 0 for plain text, 1 for HTML etc', VALUE_OPTIONAL), 1146 'description' => new external_value(core_user::get_property_type('description'), 'User profile description', VALUE_OPTIONAL), 1147 'descriptionformat' => new external_format_value(core_user::get_property_type('descriptionformat'), VALUE_OPTIONAL), 1148 'city' => new external_value(core_user::get_property_type('city'), 'Home city of the user', VALUE_OPTIONAL), 1149 'country' => new external_value(core_user::get_property_type('country'), 'Home country code of the user, such as AU or CZ', VALUE_OPTIONAL), 1150 'profileimageurlsmall' => new external_value(PARAM_URL, 'User image profile URL - small version'), 1151 'profileimageurl' => new external_value(PARAM_URL, 'User image profile URL - big version'), 1152 'customfields' => new external_multiple_structure( 1153 new external_single_structure( 1154 array( 1155 'type' => new external_value(PARAM_ALPHANUMEXT, 'The type of the custom field - text field, checkbox...'), 1156 'value' => new external_value(PARAM_RAW, 'The value of the custom field'), 1157 'name' => new external_value(PARAM_RAW, 'The name of the custom field'), 1158 'shortname' => new external_value(PARAM_RAW, 'The shortname of the custom field - to be able to build the field class in the code'), 1159 ) 1160 ), 'User custom fields (also known as user profile fields)', VALUE_OPTIONAL), 1161 'preferences' => new external_multiple_structure( 1162 new external_single_structure( 1163 array( 1164 'name' => new external_value(PARAM_RAW, 'The name of the preferences'), 1165 'value' => new external_value(PARAM_RAW, 'The value of the preference'), 1166 ) 1167 ), 'Users preferences', VALUE_OPTIONAL) 1168 ); 1169 if (!empty($additionalfields)) { 1170 $userfields = array_merge($userfields, $additionalfields); 1171 } 1172 return new external_single_structure($userfields); 1173 } 1174 1175 /** 1176 * Returns description of method parameters 1177 * 1178 * @return external_function_parameters 1179 * @since Moodle 2.6 1180 */ 1181 public static function add_user_private_files_parameters() { 1182 return new external_function_parameters( 1183 array( 1184 'draftid' => new external_value(PARAM_INT, 'draft area id') 1185 ) 1186 ); 1187 } 1188 1189 /** 1190 * Copy files from a draft area to users private files area. 1191 * 1192 * @throws invalid_parameter_exception 1193 * @throws moodle_exception 1194 * @param int $draftid Id of a draft area containing files. 1195 * @return array An array of warnings 1196 * @since Moodle 2.6 1197 */ 1198 public static function add_user_private_files($draftid) { 1199 global $CFG, $USER; 1200 require_once($CFG->libdir . "/filelib.php"); 1201 1202 $params = self::validate_parameters(self::add_user_private_files_parameters(), array('draftid' => $draftid)); 1203 1204 if (isguestuser()) { 1205 throw new invalid_parameter_exception('Guest users cannot upload files'); 1206 } 1207 1208 $context = context_user::instance($USER->id); 1209 require_capability('moodle/user:manageownfiles', $context); 1210 1211 $maxbytes = $CFG->userquota; 1212 $maxareabytes = $CFG->userquota; 1213 if (has_capability('moodle/user:ignoreuserquota', $context)) { 1214 $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS; 1215 $maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED; 1216 } else { 1217 // Get current used space for this user (private files only). 1218 $fileareainfo = file_get_file_area_info($context->id, 'user', 'private'); 1219 $usedspace = $fileareainfo['filesize_without_references']; 1220 1221 // Get the total size of the new files we want to add to private files. 1222 $newfilesinfo = file_get_draft_area_info($params['draftid']); 1223 1224 if (($newfilesinfo['filesize_without_references'] + $usedspace) > $maxareabytes) { 1225 throw new moodle_exception('maxareabytes'); 1226 } 1227 } 1228 1229 $options = array('subdirs' => 1, 1230 'maxbytes' => $maxbytes, 1231 'maxfiles' => -1, 1232 'areamaxbytes' => $maxareabytes); 1233 1234 file_merge_files_from_draft_area_into_filearea($draftid, $context->id, 'user', 'private', 0, $options); 1235 1236 return null; 1237 } 1238 1239 /** 1240 * Returns description of method result value 1241 * 1242 * @return external_description 1243 * @since Moodle 2.2 1244 */ 1245 public static function add_user_private_files_returns() { 1246 return null; 1247 } 1248 1249 /** 1250 * Returns description of method parameters. 1251 * 1252 * @return external_function_parameters 1253 * @since Moodle 2.6 1254 */ 1255 public static function add_user_device_parameters() { 1256 return new external_function_parameters( 1257 array( 1258 'appid' => new external_value(PARAM_NOTAGS, 'the app id, usually something like com.moodle.moodlemobile'), 1259 'name' => new external_value(PARAM_NOTAGS, 'the device name, \'occam\' or \'iPhone\' etc.'), 1260 'model' => new external_value(PARAM_NOTAGS, 'the device model \'Nexus4\' or \'iPad1,1\' etc.'), 1261 'platform' => new external_value(PARAM_NOTAGS, 'the device platform \'iOS\' or \'Android\' etc.'), 1262 'version' => new external_value(PARAM_NOTAGS, 'the device version \'6.1.2\' or \'4.2.2\' etc.'), 1263 'pushid' => new external_value(PARAM_RAW, 'the device PUSH token/key/identifier/registration id'), 1264 'uuid' => new external_value(PARAM_RAW, 'the device UUID'), 1265 'publickey' => new external_value(PARAM_RAW, 'the app generated public key', VALUE_DEFAULT, null), 1266 ) 1267 ); 1268 } 1269 1270 /** 1271 * Add a user device in Moodle database (for PUSH notifications usually). 1272 * 1273 * @throws moodle_exception 1274 * @param string $appid The app id, usually something like com.moodle.moodlemobile. 1275 * @param string $name The device name, occam or iPhone etc. 1276 * @param string $model The device model Nexus4 or iPad1.1 etc. 1277 * @param string $platform The device platform iOs or Android etc. 1278 * @param string $version The device version 6.1.2 or 4.2.2 etc. 1279 * @param string $pushid The device PUSH token/key/identifier/registration id. 1280 * @param string $uuid The device UUID. 1281 * @param string $publickey The app generated public key 1282 * @return array List of possible warnings. 1283 * @since Moodle 2.6 1284 */ 1285 public static function add_user_device($appid, $name, $model, $platform, $version, $pushid, $uuid, $publickey = null) { 1286 global $CFG, $USER, $DB; 1287 require_once($CFG->dirroot . "/user/lib.php"); 1288 1289 $params = self::validate_parameters(self::add_user_device_parameters(), 1290 array('appid' => $appid, 1291 'name' => $name, 1292 'model' => $model, 1293 'platform' => $platform, 1294 'version' => $version, 1295 'pushid' => $pushid, 1296 'uuid' => $uuid, 1297 'publickey' => $publickey, 1298 )); 1299 1300 $warnings = array(); 1301 1302 // Prevent duplicate keys for users. 1303 if ($DB->get_record('user_devices', array('pushid' => $params['pushid'], 'userid' => $USER->id))) { 1304 $warnings['warning'][] = array( 1305 'item' => $params['pushid'], 1306 'warningcode' => 'existingkeyforthisuser', 1307 'message' => 'This key is already stored for this user' 1308 ); 1309 return $warnings; 1310 } 1311 1312 // Notice that we can have multiple devices because previously it was allowed to have repeated ones. 1313 // Since we don't have a clear way to decide which one is the more appropiate, we update all. 1314 if ($userdevices = $DB->get_records('user_devices', array('uuid' => $params['uuid'], 1315 'appid' => $params['appid'], 'userid' => $USER->id))) { 1316 1317 foreach ($userdevices as $userdevice) { 1318 $userdevice->version = $params['version']; // Maybe the user upgraded the device. 1319 $userdevice->pushid = $params['pushid']; 1320 $userdevice->publickey = $params['publickey']; 1321 $userdevice->timemodified = time(); 1322 $DB->update_record('user_devices', $userdevice); 1323 } 1324 1325 } else { 1326 $userdevice = new stdclass; 1327 $userdevice->userid = $USER->id; 1328 $userdevice->appid = $params['appid']; 1329 $userdevice->name = $params['name']; 1330 $userdevice->model = $params['model']; 1331 $userdevice->platform = $params['platform']; 1332 $userdevice->version = $params['version']; 1333 $userdevice->pushid = $params['pushid']; 1334 $userdevice->uuid = $params['uuid']; 1335 $userdevice->publickey = $params['publickey']; 1336 $userdevice->timecreated = time(); 1337 $userdevice->timemodified = $userdevice->timecreated; 1338 1339 if (!$DB->insert_record('user_devices', $userdevice)) { 1340 throw new moodle_exception("There was a problem saving in the database the device with key: " . $params['pushid']); 1341 } 1342 } 1343 1344 return $warnings; 1345 } 1346 1347 /** 1348 * Returns description of method result value. 1349 * 1350 * @return external_multiple_structure 1351 * @since Moodle 2.6 1352 */ 1353 public static function add_user_device_returns() { 1354 return new external_multiple_structure( 1355 new external_warnings() 1356 ); 1357 } 1358 1359 /** 1360 * Returns description of method parameters. 1361 * 1362 * @return external_function_parameters 1363 * @since Moodle 2.9 1364 */ 1365 public static function remove_user_device_parameters() { 1366 return new external_function_parameters( 1367 array( 1368 'uuid' => new external_value(PARAM_RAW, 'the device UUID'), 1369 'appid' => new external_value(PARAM_NOTAGS, 1370 'the app id, if empty devices matching the UUID for the user will be removed', 1371 VALUE_DEFAULT, ''), 1372 ) 1373 ); 1374 } 1375 1376 /** 1377 * Remove a user device from the Moodle database (for PUSH notifications usually). 1378 * 1379 * @param string $uuid The device UUID. 1380 * @param string $appid The app id, opitonal parameter. If empty all the devices fmatching the UUID or the user will be removed. 1381 * @return array List of possible warnings and removal status. 1382 * @since Moodle 2.9 1383 */ 1384 public static function remove_user_device($uuid, $appid = "") { 1385 global $CFG; 1386 require_once($CFG->dirroot . "/user/lib.php"); 1387 1388 $params = self::validate_parameters(self::remove_user_device_parameters(), array('uuid' => $uuid, 'appid' => $appid)); 1389 1390 $context = context_system::instance(); 1391 self::validate_context($context); 1392 1393 // Warnings array, it can be empty at the end but is mandatory. 1394 $warnings = array(); 1395 1396 $removed = user_remove_user_device($params['uuid'], $params['appid']); 1397 1398 if (!$removed) { 1399 $warnings[] = array( 1400 'item' => $params['uuid'], 1401 'warningcode' => 'devicedoesnotexist', 1402 'message' => 'The device doesn\'t exists in the database' 1403 ); 1404 } 1405 1406 $result = array( 1407 'removed' => $removed, 1408 'warnings' => $warnings 1409 ); 1410 1411 return $result; 1412 } 1413 1414 /** 1415 * Returns description of method result value. 1416 * 1417 * @return external_multiple_structure 1418 * @since Moodle 2.9 1419 */ 1420 public static function remove_user_device_returns() { 1421 return new external_single_structure( 1422 array( 1423 'removed' => new external_value(PARAM_BOOL, 'True if removed, false if not removed because it doesn\'t exists'), 1424 'warnings' => new external_warnings(), 1425 ) 1426 ); 1427 } 1428 1429 /** 1430 * Returns description of method parameters 1431 * 1432 * @return external_function_parameters 1433 * @since Moodle 2.9 1434 */ 1435 public static function view_user_list_parameters() { 1436 return new external_function_parameters( 1437 array( 1438 'courseid' => new external_value(PARAM_INT, 'id of the course, 0 for site') 1439 ) 1440 ); 1441 } 1442 1443 /** 1444 * Trigger the user_list_viewed event. 1445 * 1446 * @param int $courseid id of course 1447 * @return array of warnings and status result 1448 * @since Moodle 2.9 1449 * @throws moodle_exception 1450 */ 1451 public static function view_user_list($courseid) { 1452 global $CFG; 1453 require_once($CFG->dirroot . "/user/lib.php"); 1454 require_once($CFG->dirroot . '/course/lib.php'); 1455 1456 $params = self::validate_parameters(self::view_user_list_parameters(), 1457 array( 1458 'courseid' => $courseid 1459 )); 1460 1461 $warnings = array(); 1462 1463 if (empty($params['courseid'])) { 1464 $params['courseid'] = SITEID; 1465 } 1466 1467 $course = get_course($params['courseid']); 1468 1469 if ($course->id == SITEID) { 1470 $context = context_system::instance(); 1471 } else { 1472 $context = context_course::instance($course->id); 1473 } 1474 self::validate_context($context); 1475 1476 course_require_view_participants($context); 1477 1478 user_list_view($course, $context); 1479 1480 $result = array(); 1481 $result['status'] = true; 1482 $result['warnings'] = $warnings; 1483 return $result; 1484 } 1485 1486 /** 1487 * Returns description of method result value 1488 * 1489 * @return external_description 1490 * @since Moodle 2.9 1491 */ 1492 public static function view_user_list_returns() { 1493 return new external_single_structure( 1494 array( 1495 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 1496 'warnings' => new external_warnings() 1497 ) 1498 ); 1499 } 1500 1501 /** 1502 * Returns description of method parameters 1503 * 1504 * @return external_function_parameters 1505 * @since Moodle 2.9 1506 */ 1507 public static function view_user_profile_parameters() { 1508 return new external_function_parameters( 1509 array( 1510 'userid' => new external_value(PARAM_INT, 'id of the user, 0 for current user', VALUE_REQUIRED), 1511 'courseid' => new external_value(PARAM_INT, 'id of the course, default site course', VALUE_DEFAULT, 0) 1512 ) 1513 ); 1514 } 1515 1516 /** 1517 * Trigger the user profile viewed event. 1518 * 1519 * @param int $userid id of user 1520 * @param int $courseid id of course 1521 * @return array of warnings and status result 1522 * @since Moodle 2.9 1523 * @throws moodle_exception 1524 */ 1525 public static function view_user_profile($userid, $courseid = 0) { 1526 global $CFG, $USER; 1527 require_once($CFG->dirroot . "/user/profile/lib.php"); 1528 1529 $params = self::validate_parameters(self::view_user_profile_parameters(), 1530 array( 1531 'userid' => $userid, 1532 'courseid' => $courseid 1533 )); 1534 1535 $warnings = array(); 1536 1537 if (empty($params['userid'])) { 1538 $params['userid'] = $USER->id; 1539 } 1540 1541 if (empty($params['courseid'])) { 1542 $params['courseid'] = SITEID; 1543 } 1544 1545 $course = get_course($params['courseid']); 1546 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 1547 core_user::require_active_user($user); 1548 1549 if ($course->id == SITEID) { 1550 $coursecontext = context_system::instance();; 1551 } else { 1552 $coursecontext = context_course::instance($course->id); 1553 } 1554 self::validate_context($coursecontext); 1555 1556 $currentuser = $USER->id == $user->id; 1557 $usercontext = context_user::instance($user->id); 1558 1559 if (!$currentuser and 1560 !has_capability('moodle/user:viewdetails', $coursecontext) and 1561 !has_capability('moodle/user:viewdetails', $usercontext)) { 1562 throw new moodle_exception('cannotviewprofile'); 1563 } 1564 1565 // Case like user/profile.php. 1566 if ($course->id == SITEID) { 1567 profile_view($user, $usercontext); 1568 } else { 1569 // Case like user/view.php. 1570 if (!$currentuser and !can_access_course($course, $user, '', true)) { 1571 throw new moodle_exception('notenrolledprofile'); 1572 } 1573 1574 profile_view($user, $coursecontext, $course); 1575 } 1576 1577 $result = array(); 1578 $result['status'] = true; 1579 $result['warnings'] = $warnings; 1580 return $result; 1581 } 1582 1583 /** 1584 * Returns description of method result value 1585 * 1586 * @return external_description 1587 * @since Moodle 2.9 1588 */ 1589 public static function view_user_profile_returns() { 1590 return new external_single_structure( 1591 array( 1592 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 1593 'warnings' => new external_warnings() 1594 ) 1595 ); 1596 } 1597 1598 /** 1599 * Returns description of method parameters 1600 * 1601 * @return external_function_parameters 1602 * @since Moodle 3.2 1603 */ 1604 public static function get_user_preferences_parameters() { 1605 return new external_function_parameters( 1606 array( 1607 'name' => new external_value(PARAM_RAW, 'preference name, empty for all', VALUE_DEFAULT, ''), 1608 'userid' => new external_value(PARAM_INT, 'id of the user, default to current user', VALUE_DEFAULT, 0) 1609 ) 1610 ); 1611 } 1612 1613 /** 1614 * Return user preferences. 1615 * 1616 * @param string $name preference name, empty for all 1617 * @param int $userid id of the user, 0 for current user 1618 * @return array of warnings and preferences 1619 * @since Moodle 3.2 1620 * @throws moodle_exception 1621 */ 1622 public static function get_user_preferences($name = '', $userid = 0) { 1623 global $USER; 1624 1625 $params = self::validate_parameters(self::get_user_preferences_parameters(), 1626 array( 1627 'name' => $name, 1628 'userid' => $userid 1629 )); 1630 $preferences = array(); 1631 $warnings = array(); 1632 1633 $context = context_system::instance(); 1634 self::validate_context($context); 1635 1636 if (empty($params['name'])) { 1637 $name = null; 1638 } 1639 if (empty($params['userid'])) { 1640 $user = null; 1641 } else { 1642 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 1643 core_user::require_active_user($user); 1644 if ($user->id != $USER->id) { 1645 // Only admins can retrieve other users preferences. 1646 require_capability('moodle/site:config', $context); 1647 } 1648 } 1649 1650 $userpreferences = get_user_preferences($name, null, $user); 1651 // Check if we received just one preference. 1652 if (!is_array($userpreferences)) { 1653 $userpreferences = array($name => $userpreferences); 1654 } 1655 1656 foreach ($userpreferences as $name => $value) { 1657 $preferences[] = array( 1658 'name' => $name, 1659 'value' => $value, 1660 ); 1661 } 1662 1663 $result = array(); 1664 $result['preferences'] = $preferences; 1665 $result['warnings'] = $warnings; 1666 return $result; 1667 } 1668 1669 /** 1670 * Returns description of method result value 1671 * 1672 * @return external_description 1673 * @since Moodle 3.2 1674 */ 1675 public static function get_user_preferences_returns() { 1676 return new external_single_structure( 1677 array( 1678 'preferences' => new external_multiple_structure( 1679 new external_single_structure( 1680 array( 1681 'name' => new external_value(PARAM_RAW, 'The name of the preference'), 1682 'value' => new external_value(PARAM_RAW, 'The value of the preference'), 1683 ) 1684 ), 1685 'User custom fields (also known as user profile fields)' 1686 ), 1687 'warnings' => new external_warnings() 1688 ) 1689 ); 1690 } 1691 1692 /** 1693 * Returns description of method parameters 1694 * 1695 * @return external_function_parameters 1696 * @since Moodle 3.2 1697 */ 1698 public static function update_picture_parameters() { 1699 return new external_function_parameters( 1700 array( 1701 'draftitemid' => new external_value(PARAM_INT, 'Id of the user draft file to use as image'), 1702 'delete' => new external_value(PARAM_BOOL, 'If we should delete the user picture', VALUE_DEFAULT, false), 1703 'userid' => new external_value(PARAM_INT, 'Id of the user, 0 for current user', VALUE_DEFAULT, 0) 1704 ) 1705 ); 1706 } 1707 1708 /** 1709 * Update or delete the user picture in the site 1710 * 1711 * @param int $draftitemid id of the user draft file to use as image 1712 * @param bool $delete if we should delete the user picture 1713 * @param int $userid id of the user, 0 for current user 1714 * @return array warnings and success status 1715 * @since Moodle 3.2 1716 * @throws moodle_exception 1717 */ 1718 public static function update_picture($draftitemid, $delete = false, $userid = 0) { 1719 global $CFG, $USER, $PAGE; 1720 1721 $params = self::validate_parameters( 1722 self::update_picture_parameters(), 1723 array( 1724 'draftitemid' => $draftitemid, 1725 'delete' => $delete, 1726 'userid' => $userid 1727 ) 1728 ); 1729 1730 $context = context_system::instance(); 1731 self::validate_context($context); 1732 1733 if (!empty($CFG->disableuserimages)) { 1734 throw new moodle_exception('userimagesdisabled', 'admin'); 1735 } 1736 1737 if (empty($params['userid']) or $params['userid'] == $USER->id) { 1738 $user = $USER; 1739 require_capability('moodle/user:editownprofile', $context); 1740 } else { 1741 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 1742 core_user::require_active_user($user); 1743 $personalcontext = context_user::instance($user->id); 1744 1745 require_capability('moodle/user:editprofile', $personalcontext); 1746 if (is_siteadmin($user) and !is_siteadmin($USER)) { // Only admins may edit other admins. 1747 throw new moodle_exception('useradmineditadmin'); 1748 } 1749 } 1750 1751 // Load the appropriate auth plugin. 1752 $userauth = get_auth_plugin($user->auth); 1753 if (is_mnet_remote_user($user) or !$userauth->can_edit_profile() or $userauth->edit_profile_url()) { 1754 throw new moodle_exception('noprofileedit', 'auth'); 1755 } 1756 1757 $filemanageroptions = array( 1758 'maxbytes' => $CFG->maxbytes, 1759 'subdirs' => 0, 1760 'maxfiles' => 1, 1761 'accepted_types' => 'optimised_image' 1762 ); 1763 $user->deletepicture = $params['delete']; 1764 $user->imagefile = $params['draftitemid']; 1765 $success = core_user::update_picture($user, $filemanageroptions); 1766 1767 $result = array( 1768 'success' => $success, 1769 'warnings' => array(), 1770 ); 1771 if ($success) { 1772 $userpicture = new user_picture(core_user::get_user($user->id)); 1773 $userpicture->size = 1; // Size f1. 1774 $result['profileimageurl'] = $userpicture->get_url($PAGE)->out(false); 1775 } 1776 return $result; 1777 } 1778 1779 /** 1780 * Returns description of method result value 1781 * 1782 * @return external_description 1783 * @since Moodle 3.2 1784 */ 1785 public static function update_picture_returns() { 1786 return new external_single_structure( 1787 array( 1788 'success' => new external_value(PARAM_BOOL, 'True if the image was updated, false otherwise.'), 1789 'profileimageurl' => new external_value(PARAM_URL, 'New profile user image url', VALUE_OPTIONAL), 1790 'warnings' => new external_warnings() 1791 ) 1792 ); 1793 } 1794 1795 /** 1796 * Returns description of method parameters 1797 * 1798 * @return external_function_parameters 1799 * @since Moodle 3.2 1800 */ 1801 public static function set_user_preferences_parameters() { 1802 return new external_function_parameters( 1803 array( 1804 'preferences' => new external_multiple_structure( 1805 new external_single_structure( 1806 array( 1807 'name' => new external_value(PARAM_RAW, 'The name of the preference'), 1808 'value' => new external_value(PARAM_RAW, 'The value of the preference'), 1809 'userid' => new external_value(PARAM_INT, 'Id of the user to set the preference'), 1810 ) 1811 ) 1812 ) 1813 ) 1814 ); 1815 } 1816 1817 /** 1818 * Set user preferences. 1819 * 1820 * @param array $preferences list of preferences including name, value and userid 1821 * @return array of warnings and preferences saved 1822 * @since Moodle 3.2 1823 * @throws moodle_exception 1824 */ 1825 public static function set_user_preferences($preferences) { 1826 global $USER; 1827 1828 $params = self::validate_parameters(self::set_user_preferences_parameters(), array('preferences' => $preferences)); 1829 $warnings = array(); 1830 $saved = array(); 1831 1832 $context = context_system::instance(); 1833 self::validate_context($context); 1834 1835 $userscache = array(); 1836 foreach ($params['preferences'] as $pref) { 1837 // Check to which user set the preference. 1838 if (!empty($userscache[$pref['userid']])) { 1839 $user = $userscache[$pref['userid']]; 1840 } else { 1841 try { 1842 $user = core_user::get_user($pref['userid'], '*', MUST_EXIST); 1843 core_user::require_active_user($user); 1844 $userscache[$pref['userid']] = $user; 1845 } catch (Exception $e) { 1846 $warnings[] = array( 1847 'item' => 'user', 1848 'itemid' => $pref['userid'], 1849 'warningcode' => 'invaliduser', 1850 'message' => $e->getMessage() 1851 ); 1852 continue; 1853 } 1854 } 1855 1856 try { 1857 if (core_user::can_edit_preference($pref['name'], $user)) { 1858 $value = core_user::clean_preference($pref['value'], $pref['name']); 1859 set_user_preference($pref['name'], $value, $user->id); 1860 $saved[] = array( 1861 'name' => $pref['name'], 1862 'userid' => $user->id, 1863 ); 1864 } else { 1865 $warnings[] = array( 1866 'item' => 'user', 1867 'itemid' => $user->id, 1868 'warningcode' => 'nopermission', 1869 'message' => 'You are not allowed to change the preference '.s($pref['name']).' for user '.$user->id 1870 ); 1871 } 1872 } catch (Exception $e) { 1873 $warnings[] = array( 1874 'item' => 'user', 1875 'itemid' => $user->id, 1876 'warningcode' => 'errorsavingpreference', 1877 'message' => $e->getMessage() 1878 ); 1879 } 1880 } 1881 1882 $result = array(); 1883 $result['saved'] = $saved; 1884 $result['warnings'] = $warnings; 1885 return $result; 1886 } 1887 1888 /** 1889 * Returns description of method result value 1890 * 1891 * @return external_description 1892 * @since Moodle 3.2 1893 */ 1894 public static function set_user_preferences_returns() { 1895 return new external_single_structure( 1896 array( 1897 'saved' => new external_multiple_structure( 1898 new external_single_structure( 1899 array( 1900 'name' => new external_value(PARAM_RAW, 'The name of the preference'), 1901 'userid' => new external_value(PARAM_INT, 'The user the preference was set for'), 1902 ) 1903 ), 'Preferences saved' 1904 ), 1905 'warnings' => new external_warnings() 1906 ) 1907 ); 1908 } 1909 1910 /** 1911 * Returns description of method parameters. 1912 * 1913 * @return external_function_parameters 1914 * @since Moodle 3.2 1915 */ 1916 public static function agree_site_policy_parameters() { 1917 return new external_function_parameters(array()); 1918 } 1919 1920 /** 1921 * Agree the site policy for the current user. 1922 * 1923 * @return array of warnings and status result 1924 * @since Moodle 3.2 1925 * @throws moodle_exception 1926 */ 1927 public static function agree_site_policy() { 1928 global $CFG, $DB, $USER; 1929 1930 $warnings = array(); 1931 1932 $context = context_system::instance(); 1933 try { 1934 // We expect an exception here since the user didn't agree the site policy yet. 1935 self::validate_context($context); 1936 } catch (Exception $e) { 1937 // We are expecting only a sitepolicynotagreed exception. 1938 if (!($e instanceof moodle_exception) or $e->errorcode != 'sitepolicynotagreed') { 1939 // In case we receive a different exception, throw it. 1940 throw $e; 1941 } 1942 } 1943 1944 $manager = new \core_privacy\local\sitepolicy\manager(); 1945 if (!empty($USER->policyagreed)) { 1946 $status = false; 1947 $warnings[] = array( 1948 'item' => 'user', 1949 'itemid' => $USER->id, 1950 'warningcode' => 'alreadyagreed', 1951 'message' => 'The user already agreed the site policy.' 1952 ); 1953 } else if (!$manager->is_defined()) { 1954 $status = false; 1955 $warnings[] = array( 1956 'item' => 'user', 1957 'itemid' => $USER->id, 1958 'warningcode' => 'nositepolicy', 1959 'message' => 'The site does not have a site policy configured.' 1960 ); 1961 } else { 1962 $status = $manager->accept(); 1963 } 1964 1965 $result = array(); 1966 $result['status'] = $status; 1967 $result['warnings'] = $warnings; 1968 return $result; 1969 } 1970 1971 /** 1972 * Returns description of method result value. 1973 * 1974 * @return external_description 1975 * @since Moodle 3.2 1976 */ 1977 public static function agree_site_policy_returns() { 1978 return new external_single_structure( 1979 array( 1980 'status' => new external_value(PARAM_BOOL, 'Status: true only if we set the policyagreed to 1 for the user'), 1981 'warnings' => new external_warnings() 1982 ) 1983 ); 1984 } 1985 1986 /** 1987 * Returns description of method parameters. 1988 * 1989 * @return external_function_parameters 1990 * @since Moodle 3.4 1991 */ 1992 public static function get_private_files_info_parameters() { 1993 return new external_function_parameters( 1994 array( 1995 'userid' => new external_value(PARAM_INT, 'Id of the user, default to current user.', VALUE_DEFAULT, 0) 1996 ) 1997 ); 1998 } 1999 2000 /** 2001 * Returns general information about files in the user private files area. 2002 * 2003 * @param int $userid Id of the user, default to current user. 2004 * @return array of warnings and file area information 2005 * @since Moodle 3.4 2006 * @throws moodle_exception 2007 */ 2008 public static function get_private_files_info($userid = 0) { 2009 global $CFG, $USER; 2010 require_once($CFG->libdir . '/filelib.php'); 2011 2012 $params = self::validate_parameters(self::get_private_files_info_parameters(), array('userid' => $userid)); 2013 $warnings = array(); 2014 2015 $context = context_system::instance(); 2016 self::validate_context($context); 2017 2018 if (empty($params['userid']) || $params['userid'] == $USER->id) { 2019 $usercontext = context_user::instance($USER->id); 2020 require_capability('moodle/user:manageownfiles', $usercontext); 2021 } else { 2022 $user = core_user::get_user($params['userid'], '*', MUST_EXIST); 2023 core_user::require_active_user($user); 2024 // Only admins can retrieve other users information. 2025 require_capability('moodle/site:config', $context); 2026 $usercontext = context_user::instance($user->id); 2027 } 2028 2029 $fileareainfo = file_get_file_area_info($usercontext->id, 'user', 'private'); 2030 2031 $result = array(); 2032 $result['filecount'] = $fileareainfo['filecount']; 2033 $result['foldercount'] = $fileareainfo['foldercount']; 2034 $result['filesize'] = $fileareainfo['filesize']; 2035 $result['filesizewithoutreferences'] = $fileareainfo['filesize_without_references']; 2036 $result['warnings'] = $warnings; 2037 return $result; 2038 } 2039 2040 /** 2041 * Returns description of method result value. 2042 * 2043 * @return external_description 2044 * @since Moodle 3.4 2045 */ 2046 public static function get_private_files_info_returns() { 2047 return new external_single_structure( 2048 array( 2049 'filecount' => new external_value(PARAM_INT, 'Number of files in the area.'), 2050 'foldercount' => new external_value(PARAM_INT, 'Number of folders in the area.'), 2051 'filesize' => new external_value(PARAM_INT, 'Total size of the files in the area.'), 2052 'filesizewithoutreferences' => new external_value(PARAM_INT, 'Total size of the area excluding file references'), 2053 'warnings' => new external_warnings() 2054 ) 2055 ); 2056 } 2057 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body