Merge branch 'MDL-62657-master' of git://github.com/junpataleta/moodle
[moodle.git] / user / tests / externallib_test.php
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/>.
17 /**
18  * User external PHPunit tests
19  *
20  * @package    core_user
21  * @category   external
22  * @copyright  2012 Jerome Mouneyrac
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @since Moodle 2.4
25  */
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
31 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
32 require_once($CFG->dirroot . '/user/externallib.php');
33 require_once($CFG->dirroot . '/files/externallib.php');
35 class core_user_externallib_testcase extends externallib_advanced_testcase {
37     /**
38      * Test get_users
39      */
40     public function test_get_users() {
41         global $USER, $CFG;
43         $this->resetAfterTest(true);
45         $course = self::getDataGenerator()->create_course();
47         $user1 = array(
48             'username' => 'usernametest1',
49             'idnumber' => 'idnumbertest1',
50             'firstname' => 'First Name User Test 1',
51             'lastname' => 'Last Name User Test 1',
52             'email' => 'usertest1@example.com',
53             'address' => '2 Test Street Perth 6000 WA',
54             'phone1' => '01010101010',
55             'phone2' => '02020203',
56             'icq' => 'testuser1',
57             'skype' => 'testuser1',
58             'yahoo' => 'testuser1',
59             'aim' => 'testuser1',
60             'msn' => 'testuser1',
61             'department' => 'Department of user 1',
62             'institution' => 'Institution of user 1',
63             'description' => 'This is a description for user 1',
64             'descriptionformat' => FORMAT_MOODLE,
65             'city' => 'Perth',
66             'url' => 'http://moodle.org',
67             'country' => 'AU'
68             );
70         $user1 = self::getDataGenerator()->create_user($user1);
71         set_config('usetags', 1);
72         require_once($CFG->dirroot . '/user/editlib.php');
73         $user1->interests = array('Cinema', 'Tennis', 'Dance', 'Guitar', 'Cooking');
74         useredit_update_interests($user1, $user1->interests);
76         $user2 = self::getDataGenerator()->create_user(
77                 array('username' => 'usernametest2', 'idnumber' => 'idnumbertest2'));
79         $generatedusers = array();
80         $generatedusers[$user1->id] = $user1;
81         $generatedusers[$user2->id] = $user2;
83         $context = context_course::instance($course->id);
84         $roleid = $this->assignUserCapability('moodle/user:viewdetails', $context->id);
86         // Enrol the users in the course.
87         $this->getDataGenerator()->enrol_user($user1->id, $course->id, $roleid);
88         $this->getDataGenerator()->enrol_user($user2->id, $course->id, $roleid);
89         $this->getDataGenerator()->enrol_user($USER->id, $course->id, $roleid);
91         // call as admin and receive all possible fields.
92         $this->setAdminUser();
94         $searchparams = array(
95             array('key' => 'invalidkey', 'value' => 'invalidkey'),
96             array('key' => 'email', 'value' => $user1->email),
97             array('key' => 'firstname', 'value' => $user1->firstname));
99         // Call the external function.
100         $result = core_user_external::get_users($searchparams);
102         // We need to execute the return values cleaning process to simulate the web service server
103         $result = external_api::clean_returnvalue(core_user_external::get_users_returns(), $result);
105         // Check we retrieve the good total number of enrolled users + no error on capability.
106         $expectedreturnedusers = 1;
107         $returnedusers = $result['users'];
108         $this->assertEquals($expectedreturnedusers, count($returnedusers));
110         foreach($returnedusers as $returneduser) {
111             $generateduser = ($returneduser['id'] == $USER->id) ?
112                                 $USER : $generatedusers[$returneduser['id']];
113             $this->assertEquals($generateduser->username, $returneduser['username']);
114             if (!empty($generateduser->idnumber)) {
115                 $this->assertEquals($generateduser->idnumber, $returneduser['idnumber']);
116             }
117             $this->assertEquals($generateduser->firstname, $returneduser['firstname']);
118             $this->assertEquals($generateduser->lastname, $returneduser['lastname']);
119             if ($generateduser->email != $USER->email) { // Don't check the tmp modified $USER email.
120                 $this->assertEquals($generateduser->email, $returneduser['email']);
121             }
122             if (!empty($generateduser->address)) {
123                 $this->assertEquals($generateduser->address, $returneduser['address']);
124             }
125             if (!empty($generateduser->phone1)) {
126                 $this->assertEquals($generateduser->phone1, $returneduser['phone1']);
127             }
128             if (!empty($generateduser->phone2)) {
129                 $this->assertEquals($generateduser->phone2, $returneduser['phone2']);
130             }
131             if (!empty($generateduser->icq)) {
132                 $this->assertEquals($generateduser->icq, $returneduser['icq']);
133             }
134             if (!empty($generateduser->skype)) {
135                 $this->assertEquals($generateduser->skype, $returneduser['skype']);
136             }
137             if (!empty($generateduser->yahoo)) {
138                 $this->assertEquals($generateduser->yahoo, $returneduser['yahoo']);
139             }
140             if (!empty($generateduser->aim)) {
141                 $this->assertEquals($generateduser->aim, $returneduser['aim']);
142             }
143             if (!empty($generateduser->msn)) {
144                 $this->assertEquals($generateduser->msn, $returneduser['msn']);
145             }
146             if (!empty($generateduser->department)) {
147                 $this->assertEquals($generateduser->department, $returneduser['department']);
148             }
149             if (!empty($generateduser->institution)) {
150                 $this->assertEquals($generateduser->institution, $returneduser['institution']);
151             }
152             if (!empty($generateduser->description)) {
153                 $this->assertEquals($generateduser->description, $returneduser['description']);
154             }
155             if (!empty($generateduser->descriptionformat)) {
156                 $this->assertEquals(FORMAT_HTML, $returneduser['descriptionformat']);
157             }
158             if (!empty($generateduser->city)) {
159                 $this->assertEquals($generateduser->city, $returneduser['city']);
160             }
161             if (!empty($generateduser->country)) {
162                 $this->assertEquals($generateduser->country, $returneduser['country']);
163             }
164             if (!empty($generateduser->url)) {
165                 $this->assertEquals($generateduser->url, $returneduser['url']);
166             }
167             if (!empty($CFG->usetags) and !empty($generateduser->interests)) {
168                 $this->assertEquals(implode(', ', $generateduser->interests), $returneduser['interests']);
169             }
170         }
172         // Test the invalid key warning.
173         $warnings = $result['warnings'];
174         $this->assertEquals(count($warnings), 1);
175         $warning = array_pop($warnings);
176         $this->assertEquals($warning['item'], 'invalidkey');
177         $this->assertEquals($warning['warningcode'], 'invalidfieldparameter');
179         // Test sending twice the same search field.
180         try {
181             $searchparams = array(
182             array('key' => 'firstname', 'value' => 'Canard'),
183             array('key' => 'email', 'value' => $user1->email),
184             array('key' => 'firstname', 'value' => $user1->firstname));
186             // Call the external function.
187             $result = core_user_external::get_users($searchparams);
188             $this->fail('Expecting \'keyalreadyset\' moodle_exception to be thrown.');
189         } catch (moodle_exception $e) {
190             $this->assertEquals('keyalreadyset', $e->errorcode);
191         } catch (Exception $e) {
192             $this->fail('Expecting \'keyalreadyset\' moodle_exception to be thrown.');
193         }
194     }
196     /**
197      * Test get_users_by_field
198      */
199     public function test_get_users_by_field() {
200         global $USER, $CFG;
202         $this->resetAfterTest(true);
204         $course = self::getDataGenerator()->create_course();
205         $user1 = array(
206             'username' => 'usernametest1',
207             'idnumber' => 'idnumbertest1',
208             'firstname' => 'First Name User Test 1',
209             'lastname' => 'Last Name User Test 1',
210             'email' => 'usertest1@example.com',
211             'address' => '2 Test Street Perth 6000 WA',
212             'phone1' => '01010101010',
213             'phone2' => '02020203',
214             'icq' => 'testuser1',
215             'skype' => 'testuser1',
216             'yahoo' => 'testuser1',
217             'aim' => 'testuser1',
218             'msn' => 'testuser1',
219             'department' => 'Department of user 1',
220             'institution' => 'Institution of user 1',
221             'description' => 'This is a description for user 1',
222             'descriptionformat' => FORMAT_MOODLE,
223             'city' => 'Perth',
224             'url' => 'http://moodle.org',
225             'country' => 'AU',
226             'lang' => 'kkl',
227             'theme' => 'kkt',
228         );
229         $user1 = self::getDataGenerator()->create_user($user1);
230         if (!empty($CFG->usetags)) {
231             require_once($CFG->dirroot . '/user/editlib.php');
232             $user1->interests = array('Cinema', 'Tennis', 'Dance', 'Guitar', 'Cooking');
233             useredit_update_interests($user1, $user1->interests);
234         }
235         $user2 = self::getDataGenerator()->create_user(
236                 array('username' => 'usernametest2', 'idnumber' => 'idnumbertest2'));
238         $generatedusers = array();
239         $generatedusers[$user1->id] = $user1;
240         $generatedusers[$user2->id] = $user2;
242         $context = context_course::instance($course->id);
243         $roleid = $this->assignUserCapability('moodle/user:viewdetails', $context->id);
245         // Enrol the users in the course.
246         $this->getDataGenerator()->enrol_user($user1->id, $course->id, $roleid, 'manual');
247         $this->getDataGenerator()->enrol_user($user2->id, $course->id, $roleid, 'manual');
248         $this->getDataGenerator()->enrol_user($USER->id, $course->id, $roleid, 'manual');
250         // call as admin and receive all possible fields.
251         $this->setAdminUser();
253         $fieldstosearch = array('id', 'idnumber', 'username', 'email');
255         foreach ($fieldstosearch as $fieldtosearch) {
257             // Call the external function.
258             $returnedusers = core_user_external::get_users_by_field($fieldtosearch,
259                         array($USER->{$fieldtosearch}, $user1->{$fieldtosearch}, $user2->{$fieldtosearch}));
260             $returnedusers = external_api::clean_returnvalue(core_user_external::get_users_by_field_returns(), $returnedusers);
262             // Expected result differ following the searched field
263             // Admin user in the PHPunit framework doesn't have an idnumber.
264             if ($fieldtosearch == 'idnumber') {
265                 $expectedreturnedusers = 2;
266             } else {
267                 $expectedreturnedusers = 3;
268             }
270             // Check we retrieve the good total number of enrolled users + no error on capability.
271             $this->assertEquals($expectedreturnedusers, count($returnedusers));
273             foreach($returnedusers as $returneduser) {
274                 $generateduser = ($returneduser['id'] == $USER->id) ?
275                                     $USER : $generatedusers[$returneduser['id']];
276                 $this->assertEquals($generateduser->username, $returneduser['username']);
277                 if (!empty($generateduser->idnumber)) {
278                     $this->assertEquals($generateduser->idnumber, $returneduser['idnumber']);
279                 }
280                 $this->assertEquals($generateduser->firstname, $returneduser['firstname']);
281                 $this->assertEquals($generateduser->lastname, $returneduser['lastname']);
282                 if ($generateduser->email != $USER->email) { //don't check the tmp modified $USER email
283                     $this->assertEquals($generateduser->email, $returneduser['email']);
284                 }
285                 if (!empty($generateduser->address)) {
286                     $this->assertEquals($generateduser->address, $returneduser['address']);
287                 }
288                 if (!empty($generateduser->phone1)) {
289                     $this->assertEquals($generateduser->phone1, $returneduser['phone1']);
290                 }
291                 if (!empty($generateduser->phone2)) {
292                     $this->assertEquals($generateduser->phone2, $returneduser['phone2']);
293                 }
294                 if (!empty($generateduser->icq)) {
295                     $this->assertEquals($generateduser->icq, $returneduser['icq']);
296                 }
297                 if (!empty($generateduser->skype)) {
298                     $this->assertEquals($generateduser->skype, $returneduser['skype']);
299                 }
300                 if (!empty($generateduser->yahoo)) {
301                     $this->assertEquals($generateduser->yahoo, $returneduser['yahoo']);
302                 }
303                 if (!empty($generateduser->aim)) {
304                     $this->assertEquals($generateduser->aim, $returneduser['aim']);
305                 }
306                 if (!empty($generateduser->msn)) {
307                     $this->assertEquals($generateduser->msn, $returneduser['msn']);
308                 }
309                 if (!empty($generateduser->department)) {
310                     $this->assertEquals($generateduser->department, $returneduser['department']);
311                 }
312                 if (!empty($generateduser->institution)) {
313                     $this->assertEquals($generateduser->institution, $returneduser['institution']);
314                 }
315                 if (!empty($generateduser->description)) {
316                     $this->assertEquals($generateduser->description, $returneduser['description']);
317                 }
318                 if (!empty($generateduser->descriptionformat) and isset($returneduser['descriptionformat'])) {
319                     $this->assertEquals($generateduser->descriptionformat, $returneduser['descriptionformat']);
320                 }
321                 if (!empty($generateduser->city)) {
322                     $this->assertEquals($generateduser->city, $returneduser['city']);
323                 }
324                 if (!empty($generateduser->country)) {
325                     $this->assertEquals($generateduser->country, $returneduser['country']);
326                 }
327                 if (!empty($generateduser->url)) {
328                     $this->assertEquals($generateduser->url, $returneduser['url']);
329                 }
330                 if (!empty($CFG->usetags) and !empty($generateduser->interests)) {
331                     $this->assertEquals(implode(', ', $generateduser->interests), $returneduser['interests']);
332                 }
333                 // Check empty since incorrect values were used when creating the user.
334                 if ($returneduser['id'] == $user1->id) {
335                     $this->assertEmpty($returneduser['lang']);
336                     $this->assertEmpty($returneduser['theme']);
337                 }
338             }
339         }
341         // Test that no result are returned for search by username if we are not admin
342         $this->setGuestUser();
344         // Call the external function.
345         $returnedusers = core_user_external::get_users_by_field('username',
346                     array($USER->username, $user1->username, $user2->username));
347         $returnedusers = external_api::clean_returnvalue(core_user_external::get_users_by_field_returns(), $returnedusers);
349         // Only the own $USER username should be returned
350         $this->assertEquals(1, count($returnedusers));
352         // And finally test as one of the enrolled users.
353         $this->setUser($user1);
355         // Call the external function.
356         $returnedusers = core_user_external::get_users_by_field('username',
357             array($USER->username, $user1->username, $user2->username));
358         $returnedusers = external_api::clean_returnvalue(core_user_external::get_users_by_field_returns(), $returnedusers);
360         // Only the own $USER username should be returned still.
361         $this->assertEquals(1, count($returnedusers));
362     }
364     public function get_course_user_profiles_setup($capability) {
365         global $USER, $CFG;
367         $this->resetAfterTest(true);
369         $return = new stdClass();
371         // Create the course and fetch its context.
372         $return->course = self::getDataGenerator()->create_course();
373         $return->user1 = array(
374             'username' => 'usernametest1',
375             'idnumber' => 'idnumbertest1',
376             'firstname' => 'First Name User Test 1',
377             'lastname' => 'Last Name User Test 1',
378             'email' => 'usertest1@example.com',
379             'address' => '2 Test Street Perth 6000 WA',
380             'phone1' => '01010101010',
381             'phone2' => '02020203',
382             'icq' => 'testuser1',
383             'skype' => 'testuser1',
384             'yahoo' => 'testuser1',
385             'aim' => 'testuser1',
386             'msn' => 'testuser1',
387             'department' => 'Department of user 1',
388             'institution' => 'Institution of user 1',
389             'description' => 'This is a description for user 1',
390             'descriptionformat' => FORMAT_MOODLE,
391             'city' => 'Perth',
392             'url' => 'http://moodle.org',
393             'country' => 'AU'
394         );
395         $return->user1 = self::getDataGenerator()->create_user($return->user1);
396         if (!empty($CFG->usetags)) {
397             require_once($CFG->dirroot . '/user/editlib.php');
398             $return->user1->interests = array('Cinema', 'Tennis', 'Dance', 'Guitar', 'Cooking');
399             useredit_update_interests($return->user1, $return->user1->interests);
400         }
401         $return->user2 = self::getDataGenerator()->create_user();
403         $context = context_course::instance($return->course->id);
404         $return->roleid = $this->assignUserCapability($capability, $context->id);
406         // Enrol the users in the course.
407         $this->getDataGenerator()->enrol_user($return->user1->id, $return->course->id, $return->roleid, 'manual');
408         $this->getDataGenerator()->enrol_user($return->user2->id, $return->course->id, $return->roleid, 'manual');
409         $this->getDataGenerator()->enrol_user($USER->id, $return->course->id, $return->roleid, 'manual');
411         return $return;
412     }
414     /**
415      * Test get_course_user_profiles
416      */
417     public function test_get_course_user_profiles() {
418         global $USER, $CFG;
420         $this->resetAfterTest(true);
422         $data = $this->get_course_user_profiles_setup('moodle/user:viewdetails');
424         // Call the external function.
425         $enrolledusers = core_user_external::get_course_user_profiles(array(
426                     array('userid' => $USER->id, 'courseid' => $data->course->id)));
428         // We need to execute the return values cleaning process to simulate the web service server.
429         $enrolledusers = external_api::clean_returnvalue(core_user_external::get_course_user_profiles_returns(), $enrolledusers);
431         // Check we retrieve the good total number of enrolled users + no error on capability.
432         $this->assertEquals(1, count($enrolledusers));
433     }
435     public function test_get_user_course_profile_as_admin() {
436         global $USER, $CFG;
438         global $USER, $CFG;
440         $this->resetAfterTest(true);
442         $data = $this->get_course_user_profiles_setup('moodle/user:viewdetails');
444         // Do the same call as admin to receive all possible fields.
445         $this->setAdminUser();
446         $USER->email = "admin@example.com";
448         // Call the external function.
449         $enrolledusers = core_user_external::get_course_user_profiles(array(
450             array('userid' => $data->user1->id, 'courseid' => $data->course->id)));
452         // We need to execute the return values cleaning process to simulate the web service server.
453         $enrolledusers = external_api::clean_returnvalue(core_user_external::get_course_user_profiles_returns(), $enrolledusers);
455         foreach($enrolledusers as $enrolleduser) {
456             if ($enrolleduser['username'] == $data->user1->username) {
457                 $this->assertEquals($data->user1->idnumber, $enrolleduser['idnumber']);
458                 $this->assertEquals($data->user1->firstname, $enrolleduser['firstname']);
459                 $this->assertEquals($data->user1->lastname, $enrolleduser['lastname']);
460                 $this->assertEquals($data->user1->email, $enrolleduser['email']);
461                 $this->assertEquals($data->user1->address, $enrolleduser['address']);
462                 $this->assertEquals($data->user1->phone1, $enrolleduser['phone1']);
463                 $this->assertEquals($data->user1->phone2, $enrolleduser['phone2']);
464                 $this->assertEquals($data->user1->icq, $enrolleduser['icq']);
465                 $this->assertEquals($data->user1->skype, $enrolleduser['skype']);
466                 $this->assertEquals($data->user1->yahoo, $enrolleduser['yahoo']);
467                 $this->assertEquals($data->user1->aim, $enrolleduser['aim']);
468                 $this->assertEquals($data->user1->msn, $enrolleduser['msn']);
469                 $this->assertEquals($data->user1->department, $enrolleduser['department']);
470                 $this->assertEquals($data->user1->institution, $enrolleduser['institution']);
471                 $this->assertEquals($data->user1->description, $enrolleduser['description']);
472                 $this->assertEquals(FORMAT_HTML, $enrolleduser['descriptionformat']);
473                 $this->assertEquals($data->user1->city, $enrolleduser['city']);
474                 $this->assertEquals($data->user1->country, $enrolleduser['country']);
475                 $this->assertEquals($data->user1->url, $enrolleduser['url']);
476                 if (!empty($CFG->usetags)) {
477                     $this->assertEquals(implode(', ', $data->user1->interests), $enrolleduser['interests']);
478                 }
479             }
480         }
481     }
483     /**
484      * Test create_users
485      */
486     public function test_create_users() {
487          global $USER, $CFG, $DB;
489         $this->resetAfterTest(true);
491         $user1 = array(
492             'username' => 'usernametest1',
493             'password' => 'Moodle2012!',
494             'idnumber' => 'idnumbertest1',
495             'firstname' => 'First Name User Test 1',
496             'lastname' => 'Last Name User Test 1',
497             'middlename' => 'Middle Name User Test 1',
498             'lastnamephonetic' => '最後のお名前のテスト一号',
499             'firstnamephonetic' => 'お名前のテスト一号',
500             'alternatename' => 'Alternate Name User Test 1',
501             'email' => 'usertest1@example.com',
502             'description' => 'This is a description for user 1',
503             'city' => 'Perth',
504             'country' => 'AU',
505             'preferences' => [[
506                     'type' => 'htmleditor',
507                     'value' => 'atto'
508                 ], [
509                     'type' => 'invalidpreference',
510                     'value' => 'abcd'
511                 ]
512             ],
513             'department' => 'College of Science',
514             'institution' => 'National Institute of Physics',
515             'phone1' => '01 2345 6789',
516             'maildisplay' => 1,
517             'interests' => 'badminton, basketball, cooking,  '
518         );
520         $context = context_system::instance();
521         $roleid = $this->assignUserCapability('moodle/user:create', $context->id);
522         $this->assignUserCapability('moodle/user:editprofile', $context->id, $roleid);
524         // Call the external function.
525         $createdusers = core_user_external::create_users(array($user1));
527         // We need to execute the return values cleaning process to simulate the web service server.
528         $createdusers = external_api::clean_returnvalue(core_user_external::create_users_returns(), $createdusers);
530         // Check we retrieve the good total number of created users + no error on capability.
531         $this->assertEquals(1, count($createdusers));
533         foreach($createdusers as $createduser) {
534             $dbuser = $DB->get_record('user', array('id' => $createduser['id']));
535             $this->assertEquals($dbuser->username, $user1['username']);
536             $this->assertEquals($dbuser->idnumber, $user1['idnumber']);
537             $this->assertEquals($dbuser->firstname, $user1['firstname']);
538             $this->assertEquals($dbuser->lastname, $user1['lastname']);
539             $this->assertEquals($dbuser->email, $user1['email']);
540             $this->assertEquals($dbuser->description, $user1['description']);
541             $this->assertEquals($dbuser->city, $user1['city']);
542             $this->assertEquals($dbuser->country, $user1['country']);
543             $this->assertEquals($dbuser->department, $user1['department']);
544             $this->assertEquals($dbuser->institution, $user1['institution']);
545             $this->assertEquals($dbuser->phone1, $user1['phone1']);
546             $this->assertEquals($dbuser->maildisplay, $user1['maildisplay']);
547             $this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
548             $this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
549             // Confirm user interests have been saved.
550             $interests = core_tag_tag::get_item_tags_array('core', 'user', $createduser['id'], core_tag_tag::BOTH_STANDARD_AND_NOT,
551                 0, false);
552             // There should be 3 user interests.
553             $this->assertCount(3, $interests);
554         }
556         // Call without required capability
557         $this->unassignUserCapability('moodle/user:create', $context->id, $roleid);
558         $this->expectException('required_capability_exception');
559         $createdusers = core_user_external::create_users(array($user1));
560     }
562     /**
563      * Test create_users with invalid parameters
564      *
565      * @dataProvider data_create_users_invalid_parameter
566      * @param array $data User data to attempt to register.
567      * @param string $expectmessage Expected exception message.
568      */
569     public function test_create_users_invalid_parameter(array $data, $expectmessage) {
570         global $USER, $CFG, $DB;
572         $this->resetAfterTest(true);
573         $this->assignUserCapability('moodle/user:create', SYSCONTEXTID);
575         $this->expectException('invalid_parameter_exception');
576         $this->expectExceptionMessage($expectmessage);
578         core_user_external::create_users(array($data));
579     }
581     /**
582      * Data provider for {@link self::test_create_users_invalid_parameter()}.
583      *
584      * @return array
585      */
586     public function data_create_users_invalid_parameter() {
587         return [
588             'blank_username' => [
589                 'data' => [
590                     'username' => '',
591                     'firstname' => 'Foo',
592                     'lastname' => 'Bar',
593                     'email' => 'foobar@example.com',
594                     'createpassword' => 1,
595                 ],
596                 'expectmessage' => 'The field username cannot be blank',
597             ],
598             'blank_firtname' => [
599                 'data' => [
600                     'username' => 'foobar',
601                     'firstname' => "\t \n",
602                     'lastname' => 'Bar',
603                     'email' => 'foobar@example.com',
604                     'createpassword' => 1,
605                 ],
606                 'expectmessage' => 'The field firstname cannot be blank',
607             ],
608             'blank_lastname' => [
609                 'data' => [
610                     'username' => 'foobar',
611                     'firstname' => '0',
612                     'lastname' => '   ',
613                     'email' => 'foobar@example.com',
614                     'createpassword' => 1,
615                 ],
616                 'expectmessage' => 'The field lastname cannot be blank',
617             ],
618             'invalid_email' => [
619                 'data' => [
620                     'username' => 'foobar',
621                     'firstname' => 'Foo',
622                     'lastname' => 'Bar',
623                     'email' => '@foobar',
624                     'createpassword' => 1,
625                 ],
626                 'expectmessage' => 'Email address is invalid',
627             ],
628             'missing_password' => [
629                 'data' => [
630                     'username' => 'foobar',
631                     'firstname' => 'Foo',
632                     'lastname' => 'Bar',
633                     'email' => 'foobar@example.com',
634                 ],
635                 'expectmessage' => 'Invalid password: you must provide a password, or set createpassword',
636             ],
637         ];
638     }
640     /**
641      * Test delete_users
642      */
643     public function test_delete_users() {
644         global $USER, $CFG, $DB;
646         $this->resetAfterTest(true);
648         $user1 = self::getDataGenerator()->create_user();
649         $user2 = self::getDataGenerator()->create_user();
651         // Check the users were correctly created.
652         $this->assertEquals(2, $DB->count_records_select('user', 'deleted = 0 AND (id = :userid1 OR id = :userid2)',
653                 array('userid1' => $user1->id, 'userid2' => $user2->id)));
655         $context = context_system::instance();
656         $roleid = $this->assignUserCapability('moodle/user:delete', $context->id);
658         // Call the external function.
659         core_user_external::delete_users(array($user1->id, $user2->id));
661         // Check we retrieve no users + no error on capability.
662         $this->assertEquals(0, $DB->count_records_select('user', 'deleted = 0 AND (id = :userid1 OR id = :userid2)',
663                 array('userid1' => $user1->id, 'userid2' => $user2->id)));
665         // Call without required capability.
666         $this->unassignUserCapability('moodle/user:delete', $context->id, $roleid);
667         $this->expectException('required_capability_exception');
668         core_user_external::delete_users(array($user1->id, $user2->id));
669     }
671     /**
672      * Test update_users
673      */
674     public function test_update_users() {
675         global $USER, $CFG, $DB;
677         $this->resetAfterTest(true);
679         $wsuser = self::getDataGenerator()->create_user();
680         self::setUser($wsuser);
682         $context = context_user::instance($USER->id);
683         $contextid = $context->id;
684         $filename = "reddot.png";
685         $filecontent = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38"
686             . "GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
688         // Call the files api to create a file.
689         $draftfile = core_files_external::upload($contextid, 'user', 'draft', 0, '/',
690                 $filename, $filecontent, null, null);
691         $draftfile = external_api::clean_returnvalue(core_files_external::upload_returns(), $draftfile);
693         $draftid = $draftfile['itemid'];
695         $user1 = self::getDataGenerator()->create_user();
697         $user1 = array(
698             'id' => $user1->id,
699             'username' => 'usernametest1',
700             'password' => 'Moodle2012!',
701             'idnumber' => 'idnumbertest1',
702             'firstname' => 'First Name User Test 1',
703             'lastname' => 'Last Name User Test 1',
704             'middlename' => 'Middle Name User Test 1',
705             'lastnamephonetic' => '最後のお名前のテスト一号',
706             'firstnamephonetic' => 'お名前のテスト一号',
707             'alternatename' => 'Alternate Name User Test 1',
708             'email' => 'usertest1@example.com',
709             'description' => 'This is a description for user 1',
710             'city' => 'Perth',
711             'userpicture' => $draftid,
712             'country' => 'AU',
713             'preferences' => [[
714                     'type' => 'htmleditor',
715                     'value' => 'atto'
716                 ], [
717                     'type' => 'invialidpreference',
718                     'value' => 'abcd'
719                 ]
720             ],
721             'department' => 'College of Science',
722             'institution' => 'National Institute of Physics',
723             'phone1' => '01 2345 6789',
724             'maildisplay' => 1,
725             'interests' => 'badminton, basketball, cooking,  '
726         );
728         $context = context_system::instance();
729         $roleid = $this->assignUserCapability('moodle/user:update', $context->id);
730         $this->assignUserCapability('moodle/user:editprofile', $context->id, $roleid);
732         // Check we can't update deleted users, guest users, site admin.
733         $user2 = $user3 = $user4 = $user1;
734         $user2['id'] = $CFG->siteguest;
736         $siteadmins = explode(',', $CFG->siteadmins);
737         $user3['id'] = array_shift($siteadmins);
739         $userdeleted = self::getDataGenerator()->create_user();
740         $user4['id'] = $userdeleted->id;
741         user_delete_user($userdeleted);
743         // Call the external function.
744         core_user_external::update_users(array($user1, $user2, $user3, $user4));
746         $dbuser2 = $DB->get_record('user', array('id' => $user2['id']));
747         $this->assertNotEquals($dbuser2->username, $user2['username']);
748         $dbuser3 = $DB->get_record('user', array('id' => $user3['id']));
749         $this->assertNotEquals($dbuser3->username, $user3['username']);
750         $dbuser4 = $DB->get_record('user', array('id' => $user4['id']));
751         $this->assertNotEquals($dbuser4->username, $user4['username']);
753         $dbuser = $DB->get_record('user', array('id' => $user1['id']));
754         $this->assertEquals($dbuser->username, $user1['username']);
755         $this->assertEquals($dbuser->idnumber, $user1['idnumber']);
756         $this->assertEquals($dbuser->firstname, $user1['firstname']);
757         $this->assertEquals($dbuser->lastname, $user1['lastname']);
758         $this->assertEquals($dbuser->email, $user1['email']);
759         $this->assertEquals($dbuser->description, $user1['description']);
760         $this->assertEquals($dbuser->city, $user1['city']);
761         $this->assertEquals($dbuser->country, $user1['country']);
762         $this->assertNotEquals(0, $dbuser->picture, 'Picture must be set to the new icon itemid for this user');
763         $this->assertEquals($dbuser->department, $user1['department']);
764         $this->assertEquals($dbuser->institution, $user1['institution']);
765         $this->assertEquals($dbuser->phone1, $user1['phone1']);
766         $this->assertEquals($dbuser->maildisplay, $user1['maildisplay']);
767         $this->assertEquals('atto', get_user_preferences('htmleditor', null, $dbuser));
768         $this->assertEquals(null, get_user_preferences('invalidpreference', null, $dbuser));
770         // Confirm user interests have been saved.
771         $interests = core_tag_tag::get_item_tags_array('core', 'user', $user1['id'], core_tag_tag::BOTH_STANDARD_AND_NOT, 0, false);
772         // There should be 3 user interests.
773         $this->assertCount(3, $interests);
775         // Confirm no picture change when parameter is not supplied.
776         unset($user1['userpicture']);
777         core_user_external::update_users(array($user1));
778         $dbusernopic = $DB->get_record('user', array('id' => $user1['id']));
779         $this->assertEquals($dbuser->picture, $dbusernopic->picture, 'Picture not change without the parameter.');
781         // Confirm delete of picture deletes the picture from the user record.
782         $user1['userpicture'] = 0;
783         core_user_external::update_users(array($user1));
784         $dbuserdelpic = $DB->get_record('user', array('id' => $user1['id']));
785         $this->assertEquals(0, $dbuserdelpic->picture, 'Picture must be deleted when sent as 0.');
788         // Call without required capability.
789         $this->unassignUserCapability('moodle/user:update', $context->id, $roleid);
790         $this->expectException('required_capability_exception');
791         core_user_external::update_users(array($user1));
792     }
794     /**
795      * Test update_users using duplicated email.
796      */
797     public function test_update_users_duplicated_email() {
798         global $DB, $CFG;
800         $this->resetAfterTest(true);
801         $this->setAdminUser();
803         $user1 = self::getDataGenerator()->create_user();
804         $user2 = self::getDataGenerator()->create_user();
805         $user2toupdate = array(
806             'id' => $user2->id,
807             'email' => $user1->email,
808         );
809         // E-mail duplicated not allowed.
810         $CFG->allowaccountssameemail = 0;
811         core_user_external::update_users(array($user2toupdate));
812         $this->assertNotEquals($user1->email, $DB->get_field('user', 'email', array('id' => $user2->id)));
813         // E-mail duplicated allowed.
814         $CFG->allowaccountssameemail = 1;
815         core_user_external::update_users(array($user2toupdate));
816         $this->assertEquals($user1->email, $DB->get_field('user', 'email', array('id' => $user2->id)));
817     }
819     /**
820      * Test add_user_private_files
821      */
822     public function test_add_user_private_files() {
823         global $USER, $CFG, $DB;
825         $this->resetAfterTest(true);
827         $context = context_system::instance();
828         $roleid = $this->assignUserCapability('moodle/user:manageownfiles', $context->id);
830         $context = context_user::instance($USER->id);
831         $contextid = $context->id;
832         $component = "user";
833         $filearea = "draft";
834         $itemid = 0;
835         $filepath = "/";
836         $filename = "Simple.txt";
837         $filecontent = base64_encode("Let us create a nice simple file");
838         $contextlevel = null;
839         $instanceid = null;
840         $browser = get_file_browser();
842         // Call the files api to create a file.
843         $draftfile = core_files_external::upload($contextid, $component, $filearea, $itemid, $filepath,
844                                                  $filename, $filecontent, $contextlevel, $instanceid);
845         $draftfile = external_api::clean_returnvalue(core_files_external::upload_returns(), $draftfile);
847         $draftid = $draftfile['itemid'];
848         // Make sure the file was created.
849         $file = $browser->get_file_info($context, $component, $filearea, $draftid, $filepath, $filename);
850         $this->assertNotEmpty($file);
852         // Make sure the file does not exist in the user private files.
853         $file = $browser->get_file_info($context, $component, 'private', 0, $filepath, $filename);
854         $this->assertEmpty($file);
856         // Call the external function.
857         core_user_external::add_user_private_files($draftid);
859         // Make sure the file was added to the user private files.
860         $file = $browser->get_file_info($context, $component, 'private', 0, $filepath, $filename);
861         $this->assertNotEmpty($file);
862     }
864     /**
865      * Test add user device
866      */
867     public function test_add_user_device() {
868         global $USER, $CFG, $DB;
870         $this->resetAfterTest(true);
872         $device = array(
873                 'appid' => 'com.moodle.moodlemobile',
874                 'name' => 'occam',
875                 'model' => 'Nexus 4',
876                 'platform' => 'Android',
877                 'version' => '4.2.2',
878                 'pushid' => 'apushdkasdfj4835',
879                 'uuid' => 'asdnfl348qlksfaasef859'
880                 );
882         // Call the external function.
883         core_user_external::add_user_device($device['appid'], $device['name'], $device['model'], $device['platform'],
884                                             $device['version'], $device['pushid'], $device['uuid']);
886         $created = $DB->get_record('user_devices', array('pushid' => $device['pushid']));
887         $created = (array) $created;
889         $this->assertEquals($device, array_intersect_key((array)$created, $device));
891         // Test reuse the same pushid value.
892         $warnings = core_user_external::add_user_device($device['appid'], $device['name'], $device['model'], $device['platform'],
893                                                         $device['version'], $device['pushid'], $device['uuid']);
894         // We need to execute the return values cleaning process to simulate the web service server.
895         $warnings = external_api::clean_returnvalue(core_user_external::add_user_device_returns(), $warnings);
896         $this->assertCount(1, $warnings);
898         // Test update an existing device.
899         $device['pushid'] = 'different than before';
900         $warnings = core_user_external::add_user_device($device['appid'], $device['name'], $device['model'], $device['platform'],
901                                                         $device['version'], $device['pushid'], $device['uuid']);
902         $warnings = external_api::clean_returnvalue(core_user_external::add_user_device_returns(), $warnings);
904         $this->assertEquals(1, $DB->count_records('user_devices'));
905         $updated = $DB->get_record('user_devices', array('pushid' => $device['pushid']));
906         $this->assertEquals($device, array_intersect_key((array)$updated, $device));
908         // Test creating a new device just changing the uuid.
909         $device['uuid'] = 'newuidforthesameuser';
910         $device['pushid'] = 'new different than before';
911         $warnings = core_user_external::add_user_device($device['appid'], $device['name'], $device['model'], $device['platform'],
912                                                         $device['version'], $device['pushid'], $device['uuid']);
913         $warnings = external_api::clean_returnvalue(core_user_external::add_user_device_returns(), $warnings);
914         $this->assertEquals(2, $DB->count_records('user_devices'));
915     }
917     /**
918      * Test remove user device
919      */
920     public function test_remove_user_device() {
921         global $USER, $CFG, $DB;
923         $this->resetAfterTest(true);
925         $device = array(
926                 'appid' => 'com.moodle.moodlemobile',
927                 'name' => 'occam',
928                 'model' => 'Nexus 4',
929                 'platform' => 'Android',
930                 'version' => '4.2.2',
931                 'pushid' => 'apushdkasdfj4835',
932                 'uuid' => 'ABCDE3723ksdfhasfaasef859'
933                 );
935         // A device with the same properties except the appid and pushid.
936         $device2 = $device;
937         $device2['pushid'] = "0987654321";
938         $device2['appid'] = "other.app.com";
940         $this->setAdminUser();
941         // Create a user device using the external API function.
942         core_user_external::add_user_device($device['appid'], $device['name'], $device['model'], $device['platform'],
943                                             $device['version'], $device['pushid'], $device['uuid']);
945         // Create the same device but for a different app.
946         core_user_external::add_user_device($device2['appid'], $device2['name'], $device2['model'], $device2['platform'],
947                                             $device2['version'], $device2['pushid'], $device2['uuid']);
949         // Try to remove a device that does not exist.
950         $result = core_user_external::remove_user_device('1234567890');
951         $result = external_api::clean_returnvalue(core_user_external::remove_user_device_returns(), $result);
952         $this->assertFalse($result['removed']);
953         $this->assertCount(1, $result['warnings']);
955         // Try to remove a device that does not exist for an existing app.
956         $result = core_user_external::remove_user_device('1234567890', $device['appid']);
957         $result = external_api::clean_returnvalue(core_user_external::remove_user_device_returns(), $result);
958         $this->assertFalse($result['removed']);
959         $this->assertCount(1, $result['warnings']);
961         // Remove an existing device for an existing app. This will remove one of the two devices.
962         $result = core_user_external::remove_user_device($device['uuid'], $device['appid']);
963         $result = external_api::clean_returnvalue(core_user_external::remove_user_device_returns(), $result);
964         $this->assertTrue($result['removed']);
966         // Remove all the devices. This must remove the remaining device.
967         $result = core_user_external::remove_user_device($device['uuid']);
968         $result = external_api::clean_returnvalue(core_user_external::remove_user_device_returns(), $result);
969         $this->assertTrue($result['removed']);
970     }
972     /**
973      * Test get_user_preferences
974      */
975     public function test_get_user_preferences() {
976         $this->resetAfterTest(true);
978         $user = self::getDataGenerator()->create_user();
979         set_user_preference('calendar_maxevents', 1, $user);
980         set_user_preference('some_random_text', 'text', $user);
982         $this->setUser($user);
984         $result = core_user_external::get_user_preferences();
985         $result = external_api::clean_returnvalue(core_user_external::get_user_preferences_returns(), $result);
986         $this->assertCount(0, $result['warnings']);
987         // Expect 3, _lastloaded is always returned.
988         $this->assertCount(3, $result['preferences']);
990         foreach ($result['preferences'] as $pref) {
991             if ($pref['name'] === '_lastloaded') {
992                 continue;
993             }
994             // Check we receive the expected preferences.
995             $this->assertEquals(get_user_preferences($pref['name']), $pref['value']);
996         }
998         // Retrieve just one preference.
999         $result = core_user_external::get_user_preferences('some_random_text');
1000         $result = external_api::clean_returnvalue(core_user_external::get_user_preferences_returns(), $result);
1001         $this->assertCount(0, $result['warnings']);
1002         $this->assertCount(1, $result['preferences']);
1003         $this->assertEquals('text', $result['preferences'][0]['value']);
1005         // Retrieve non-existent preference.
1006         $result = core_user_external::get_user_preferences('non_existent');
1007         $result = external_api::clean_returnvalue(core_user_external::get_user_preferences_returns(), $result);
1008         $this->assertCount(0, $result['warnings']);
1009         $this->assertCount(1, $result['preferences']);
1010         $this->assertEquals(null, $result['preferences'][0]['value']);
1012         // Check that as admin we can retrieve all the preferences for any user.
1013         $this->setAdminUser();
1014         $result = core_user_external::get_user_preferences('', $user->id);
1015         $result = external_api::clean_returnvalue(core_user_external::get_user_preferences_returns(), $result);
1016         $this->assertCount(0, $result['warnings']);
1017         $this->assertCount(3, $result['preferences']);
1019         foreach ($result['preferences'] as $pref) {
1020             if ($pref['name'] === '_lastloaded') {
1021                 continue;
1022             }
1023             // Check we receive the expected preferences.
1024             $this->assertEquals(get_user_preferences($pref['name'], null, $user), $pref['value']);
1025         }
1027         // Check that as a non admin user we cannot retrieve other users preferences.
1028         $anotheruser = self::getDataGenerator()->create_user();
1029         $this->setUser($anotheruser);
1031         $this->expectException('required_capability_exception');
1032         $result = core_user_external::get_user_preferences('', $user->id);
1033     }
1035     /**
1036      * Test update_picture
1037      */
1038     public function test_update_picture() {
1039         global $DB, $USER;
1041         $this->resetAfterTest(true);
1043         $user = self::getDataGenerator()->create_user();
1044         self::setUser($user);
1046         $context = context_user::instance($USER->id);
1047         $contextid = $context->id;
1048         $filename = "reddot.png";
1049         $filecontent = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38"
1050             . "GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
1052         // Call the files api to create a file.
1053         $draftfile = core_files_external::upload($contextid, 'user', 'draft', 0, '/', $filename, $filecontent, null, null);
1054         $draftid = $draftfile['itemid'];
1056         // Change user profile image.
1057         $result = core_user_external::update_picture($draftid);
1058         $result = external_api::clean_returnvalue(core_user_external::update_picture_returns(), $result);
1059         $picture = $DB->get_field('user', 'picture', array('id' => $user->id));
1060         // The new revision is in the url for the user.
1061         $this->assertContains($picture, $result['profileimageurl']);
1062         // Check expected URL for serving the image.
1063         $this->assertContains("/$contextid/user/icon", $result['profileimageurl']);
1065         // Delete image.
1066         $result = core_user_external::update_picture(0, true);
1067         $result = external_api::clean_returnvalue(core_user_external::update_picture_returns(), $result);
1068         $picture = $DB->get_field('user', 'picture', array('id' => $user->id));
1069         // No picture.
1070         $this->assertEquals(0, $picture);
1072         // Add again the user profile image (as admin).
1073         $this->setAdminUser();
1075         $context = context_user::instance($USER->id);
1076         $admincontextid = $context->id;
1077         $draftfile = core_files_external::upload($admincontextid, 'user', 'draft', 0, '/', $filename, $filecontent, null, null);
1078         $draftid = $draftfile['itemid'];
1080         $result = core_user_external::update_picture($draftid, false, $user->id);
1081         $result = external_api::clean_returnvalue(core_user_external::update_picture_returns(), $result);
1082         // The new revision is in the url for the user.
1083         $picture = $DB->get_field('user', 'picture', array('id' => $user->id));
1084         $this->assertContains($picture, $result['profileimageurl']);
1085         $this->assertContains("/$contextid/user/icon", $result['profileimageurl']);
1086     }
1088     /**
1089      * Test update_picture disabled
1090      */
1091     public function test_update_picture_disabled() {
1092         global $CFG;
1093         $this->resetAfterTest(true);
1094         $CFG->disableuserimages = true;
1096         $this->setAdminUser();
1097         $this->expectException('moodle_exception');
1098         core_user_external::update_picture(0);
1099     }
1101     /**
1102      * Test set_user_preferences
1103      */
1104     public function test_set_user_preferences_save() {
1105         global $DB;
1106         $this->resetAfterTest(true);
1108         $user1 = self::getDataGenerator()->create_user();
1109         $user2 = self::getDataGenerator()->create_user();
1111         // Save users preferences.
1112         $this->setAdminUser();
1113         $preferences = array(
1114             array(
1115                 'name' => 'htmleditor',
1116                 'value' => 'atto',
1117                 'userid' => $user1->id,
1118             ),
1119             array(
1120                 'name' => 'htmleditor',
1121                 'value' => 'tinymce',
1122                 'userid' => $user2->id,
1123             )
1124         );
1126         $result = core_user_external::set_user_preferences($preferences);
1127         $result = external_api::clean_returnvalue(core_user_external::set_user_preferences_returns(), $result);
1128         $this->assertCount(0, $result['warnings']);
1129         $this->assertCount(2, $result['saved']);
1131         // Get preference from DB to avoid cache.
1132         $this->assertEquals('atto', $DB->get_field('user_preferences', 'value',
1133             array('userid' => $user1->id, 'name' => 'htmleditor')));
1134         $this->assertEquals('tinymce', $DB->get_field('user_preferences', 'value',
1135             array('userid' => $user2->id, 'name' => 'htmleditor')));
1136     }
1138     /**
1139      * Test set_user_preferences
1140      */
1141     public function test_set_user_preferences_save_invalid_pref() {
1142         global $DB;
1143         $this->resetAfterTest(true);
1145         $user1 = self::getDataGenerator()->create_user();
1147         // Save users preferences.
1148         $this->setAdminUser();
1149         $preferences = array(
1150             array(
1151                 'name' => 'some_random_pref',
1152                 'value' => 'abc',
1153                 'userid' => $user1->id,
1154             ),
1155         );
1157         $result = core_user_external::set_user_preferences($preferences);
1158         $result = external_api::clean_returnvalue(core_user_external::set_user_preferences_returns(), $result);
1159         $this->assertCount(1, $result['warnings']);
1160         $this->assertCount(0, $result['saved']);
1161         $this->assertEquals('nopermission', $result['warnings'][0]['warningcode']);
1163         // Nothing was written to DB.
1164         $this->assertEmpty($DB->count_records('user_preferences', array('name' => 'some_random_pref')));
1165     }
1167     /**
1168      * Test set_user_preferences for an invalid user
1169      */
1170     public function test_set_user_preferences_invalid_user() {
1171         $this->resetAfterTest(true);
1173         $this->setAdminUser();
1174         $preferences = array(
1175             array(
1176                 'name' => 'calendar_maxevents',
1177                 'value' => 4,
1178                 'userid' => -2
1179             )
1180         );
1182         $result = core_user_external::set_user_preferences($preferences);
1183         $result = external_api::clean_returnvalue(core_user_external::set_user_preferences_returns(), $result);
1184         $this->assertCount(1, $result['warnings']);
1185         $this->assertCount(0, $result['saved']);
1186         $this->assertEquals('invaliduser', $result['warnings'][0]['warningcode']);
1187         $this->assertEquals(-2, $result['warnings'][0]['itemid']);
1188     }
1190     /**
1191      * Test set_user_preferences using an invalid preference
1192      */
1193     public function test_set_user_preferences_invalid_preference() {
1194         global $USER, $DB;
1196         $this->resetAfterTest(true);
1197         // Create a very long value.
1198         $this->setAdminUser();
1199         $preferences = array(
1200             array(
1201                 'name' => 'calendar_maxevents',
1202                 'value' => str_repeat('a', 1334),
1203                 'userid' => $USER->id
1204             )
1205         );
1207         $result = core_user_external::set_user_preferences($preferences);
1208         $result = external_api::clean_returnvalue(core_user_external::set_user_preferences_returns(), $result);
1209         $this->assertCount(0, $result['warnings']);
1210         $this->assertCount(1, $result['saved']);
1211         // Cleaned valud of the preference was saved.
1212         $this->assertEquals(1, $DB->get_field('user_preferences', 'value',
1213             array('userid' => $USER->id, 'name' => 'calendar_maxevents')));
1214     }
1216     /**
1217      * Test set_user_preferences for other user not being admin
1218      */
1219     public function test_set_user_preferences_capability() {
1220         $this->resetAfterTest(true);
1222         $user1 = self::getDataGenerator()->create_user();
1223         $user2 = self::getDataGenerator()->create_user();
1225         $this->setUser($user1);
1226         $preferences = array(
1227             array(
1228                 'name' => 'calendar_maxevents',
1229                 'value' => 4,
1230                 'userid' => $user2->id
1231             )
1232         );
1234         $result = core_user_external::set_user_preferences($preferences);
1236         $this->assertCount(1, $result['warnings']);
1237         $this->assertCount(0, $result['saved']);
1238         $this->assertEquals('nopermission', $result['warnings'][0]['warningcode']);
1239         $this->assertEquals($user2->id, $result['warnings'][0]['itemid']);
1240     }
1242     /**
1243      * Test agree_site_policy
1244      */
1245     public function test_agree_site_policy() {
1246         global $CFG, $DB, $USER;
1247         $this->resetAfterTest(true);
1249         $user = self::getDataGenerator()->create_user();
1250         $this->setUser($user);
1252         // Site policy not set.
1253         $result = core_user_external::agree_site_policy();
1254         $result = external_api::clean_returnvalue(core_user_external::agree_site_policy_returns(), $result);
1255         $this->assertFalse($result['status']);
1256         $this->assertCount(1, $result['warnings']);
1257         $this->assertEquals('nositepolicy', $result['warnings'][0]['warningcode']);
1259         // Set a policy issue.
1260         $CFG->sitepolicy = 'https://moodle.org';
1261         $this->assertEquals(0, $USER->policyagreed);
1263         $result = core_user_external::agree_site_policy();
1264         $result = external_api::clean_returnvalue(core_user_external::agree_site_policy_returns(), $result);
1265         $this->assertTrue($result['status']);
1266         $this->assertCount(0, $result['warnings']);
1267         $this->assertEquals(1, $USER->policyagreed);
1268         $this->assertEquals(1, $DB->get_field('user', 'policyagreed', array('id' => $USER->id)));
1270         // Try again, we should get a warning.
1271         $result = core_user_external::agree_site_policy();
1272         $result = external_api::clean_returnvalue(core_user_external::agree_site_policy_returns(), $result);
1273         $this->assertFalse($result['status']);
1274         $this->assertCount(1, $result['warnings']);
1275         $this->assertEquals('alreadyagreed', $result['warnings'][0]['warningcode']);
1277         // Set something to make require_login throws an exception.
1278         $otheruser = self::getDataGenerator()->create_user();
1279         $this->setUser($otheruser);
1281         $DB->set_field('user', 'lastname', '', array('id' => $USER->id));
1282         $USER->lastname = '';
1283         try {
1284             $result = core_user_external::agree_site_policy();
1285             $this->fail('Expecting \'usernotfullysetup\' moodle_exception to be thrown');
1286         } catch (moodle_exception $e) {
1287             $this->assertEquals('usernotfullysetup', $e->errorcode);
1288         } catch (Exception $e) {
1289             $this->fail('Expecting \'usernotfullysetup\' moodle_exception to be thrown.');
1290         }
1291     }
1293     /**
1294      * Test get_private_files_info
1295      */
1296     public function test_get_private_files_info() {
1298         $this->resetAfterTest(true);
1299         $user = self::getDataGenerator()->create_user();
1300         $this->setUser($user);
1301         $usercontext = context_user::instance($user->id);
1303         $filerecord = array(
1304             'contextid' => $usercontext->id,
1305             'component' => 'user',
1306             'filearea'  => 'private',
1307             'itemid'    => 0,
1308             'filepath'  => '/',
1309             'filename'  => 'thefile',
1310         );
1312         $fs = get_file_storage();
1313         $file = $fs->create_file_from_string($filerecord, 'abc');
1315         // Get my private files information.
1316         $result = core_user_external::get_private_files_info();
1317         $result = external_api::clean_returnvalue(core_user_external::get_private_files_info_returns(), $result);
1318         $this->assertEquals(1, $result['filecount']);
1319         $this->assertEquals($file->get_filesize(), $result['filesize']);
1320         $this->assertEquals(0, $result['foldercount']);
1321         $this->assertEquals($file->get_filesize(), $result['filesizewithoutreferences']);
1323         // As admin, get user information.
1324         $this->setAdminUser();
1325         $result = core_user_external::get_private_files_info($user->id);
1326         $result = external_api::clean_returnvalue(core_user_external::get_private_files_info_returns(), $result);
1327         $this->assertEquals(1, $result['filecount']);
1328         $this->assertEquals($file->get_filesize(), $result['filesize']);
1329         $this->assertEquals(0, $result['foldercount']);
1330         $this->assertEquals($file->get_filesize(), $result['filesizewithoutreferences']);
1331     }
1333     /**
1334      * Test get_private_files_info missing permissions.
1335      */
1336     public function test_get_private_files_info_missing_permissions() {
1338         $this->resetAfterTest(true);
1339         $user1 = self::getDataGenerator()->create_user();
1340         $user2 = self::getDataGenerator()->create_user();
1341         $this->setUser($user1);
1343         $this->expectException('required_capability_exception');
1344         // Try to retrieve other user private files info.
1345         core_user_external::get_private_files_info($user2->id);
1346     }