MDL-50704 user: Do not validate timezones in user objects
[moodle.git] / competency / tests / external_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  * External tests.
19  *
20  * @package    core_competency
21  * @copyright  2016 Frédéric Massart - FMCorz.net
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
26 global $CFG;
28 require_once($CFG->dirroot . '/webservice/tests/helpers.php');
30 use core_competency\api;
31 use core_competency\course_competency_settings;
32 use core_competency\external;
33 use core_competency\invalid_persistent_exception;
34 use core_competency\plan;
35 use core_competency\plan_competency;
36 use core_competency\related_competency;
37 use core_competency\template;
38 use core_competency\template_competency;
39 use core_competency\user_competency;
40 use core_competency\user_competency_plan;
42 /**
43  * External testcase.
44  *
45  * @package    core_competency
46  * @copyright  2016 Frédéric Massart - FMCorz.net
47  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
48  */
49 class core_competency_external_testcase extends externallib_advanced_testcase {
51     /** @var stdClass $creator User with enough permissions to create insystem context. */
52     protected $creator = null;
54     /** @var stdClass $learningplancreator User with enough permissions to create incategory context. */
55     protected $catcreator = null;
57     /** @var stdClass $category Category */
58     protected $category = null;
60     /** @var stdClass $user User with enough permissions to view insystem context */
61     protected $user = null;
63     /** @var stdClass $catuser User with enough permissions to view incategory context */
64     protected $catuser = null;
66     /** @var int Creator role id */
67     protected $creatorrole = null;
69     /** @var int User role id */
70     protected $userrole = null;
72     /** @var string scaleconfiguration */
73     protected $scaleconfiguration1 = null;
75     /** @var string scaleconfiguration */
76     protected $scaleconfiguration2 = null;
78     /** @var string catscaleconfiguration */
79     protected $scaleconfiguration3 = null;
81     /** @var string catscaleconfiguration */
82     protected $catscaleconfiguration4 = null;
84     /**
85      * Setup function- we will create a course and add an assign instance to it.
86      */
87     protected function setUp() {
88         global $DB;
90         $this->resetAfterTest(true);
92         // Create some users.
93         $creator = $this->getDataGenerator()->create_user();
94         $user = $this->getDataGenerator()->create_user();
95         $catuser = $this->getDataGenerator()->create_user();
96         $category = $this->getDataGenerator()->create_category();
97         $othercategory = $this->getDataGenerator()->create_category();
98         $catcreator = $this->getDataGenerator()->create_user();
100         $syscontext = context_system::instance();
101         $catcontext = context_coursecat::instance($category->id);
102         $othercatcontext = context_coursecat::instance($othercategory->id);
104         // Fetching default authenticated user role.
105         $userroles = get_archetype_roles('user');
106         $this->assertCount(1, $userroles);
107         $authrole = array_pop($userroles);
109         // Reset all default authenticated users permissions.
110         unassign_capability('moodle/competency:competencygrade', $authrole->id);
111         unassign_capability('moodle/competency:competencymanage', $authrole->id);
112         unassign_capability('moodle/competency:competencyview', $authrole->id);
113         unassign_capability('moodle/competency:planmanage', $authrole->id);
114         unassign_capability('moodle/competency:planmanagedraft', $authrole->id);
115         unassign_capability('moodle/competency:planmanageown', $authrole->id);
116         unassign_capability('moodle/competency:planview', $authrole->id);
117         unassign_capability('moodle/competency:planviewdraft', $authrole->id);
118         unassign_capability('moodle/competency:planviewown', $authrole->id);
119         unassign_capability('moodle/competency:planviewowndraft', $authrole->id);
120         unassign_capability('moodle/competency:templatemanage', $authrole->id);
121         unassign_capability('moodle/competency:templateview', $authrole->id);
122         unassign_capability('moodle/cohort:manage', $authrole->id);
123         unassign_capability('moodle/competency:coursecompetencyconfigure', $authrole->id);
125         // Creating specific roles.
126         $this->creatorrole = create_role('Creator role', 'creatorrole', 'learning plan creator role description');
127         $this->userrole = create_role('User role', 'userrole', 'learning plan user role description');
129         assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
130         assign_capability('moodle/competency:competencycompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
131         assign_capability('moodle/competency:competencyview', CAP_ALLOW, $this->userrole, $syscontext->id);
132         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
133         assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
134         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
135         assign_capability('moodle/competency:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id);
136         assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
137         assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
138         assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $this->creatorrole, $syscontext->id);
139         assign_capability('moodle/cohort:manage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
140         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontext->id);
141         assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id);
142         assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
144         role_assign($this->creatorrole, $creator->id, $syscontext->id);
145         role_assign($this->creatorrole, $catcreator->id, $catcontext->id);
146         role_assign($this->userrole, $user->id, $syscontext->id);
147         role_assign($this->userrole, $catuser->id, $catcontext->id);
149         $this->creator = $creator;
150         $this->catcreator = $catcreator;
151         $this->user = $user;
152         $this->catuser = $catuser;
153         $this->category = $category;
154         $this->othercategory = $othercategory;
156         $this->getDataGenerator()->create_scale(array("id" => "1", "scale" => "value1, value2"));
157         $this->getDataGenerator()->create_scale(array("id" => "2", "scale" => "value3, value4"));
158         $this->getDataGenerator()->create_scale(array("id" => "3", "scale" => "value5, value6"));
159         $this->getDataGenerator()->create_scale(array("id" => "4", "scale" => "value7, value8"));
161         $this->scaleconfiguration1 = '[{"scaleid":"1"},{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
162                 '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
163         $this->scaleconfiguration2 = '[{"scaleid":"2"},{"name":"value3","id":1,"scaledefault":1,"proficient":0},' .
164                 '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
165         $this->scaleconfiguration3 = '[{"scaleid":"3"},{"name":"value5","id":1,"scaledefault":1,"proficient":0},' .
166                 '{"name":"value6","id":2,"scaledefault":0,"proficient":1}]';
167         $this->scaleconfiguration4 = '[{"scaleid":"4"},{"name":"value8","id":1,"scaledefault":1,"proficient":0},' .
168                 '{"name":"value8","id":2,"scaledefault":0,"proficient":1}]';
169         accesslib_clear_all_caches_for_unit_testing();
170     }
173     protected function create_competency_framework($number = 1, $system = true) {
174         $scalepropname = 'scaleconfiguration' . $number;
175         $framework = array(
176             'shortname' => 'shortname' . $number,
177             'idnumber' => 'idnumber' . $number,
178             'description' => 'description' . $number,
179             'descriptionformat' => FORMAT_HTML,
180             'scaleid' => $number,
181             'scaleconfiguration' => $this->$scalepropname,
182             'visible' => true,
183             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
184         );
185         $result = external::create_competency_framework($framework);
186         return (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result);
187     }
189     protected function create_plan($number, $userid, $templateid, $status, $duedate) {
190         $plan = array(
191             'name' => 'name' . $number,
192             'description' => 'description' . $number,
193             'descriptionformat' => FORMAT_HTML,
194             'userid' => $userid,
195             'templateid' => empty($templateid) ? null : $templateid,
196             'status' => $status,
197             'duedate' => $duedate
198         );
199         $result = external::create_plan($plan);
200         return (object) external_api::clean_returnvalue(external::create_plan_returns(), $result);
201     }
203     protected function create_template($number, $system) {
204         $template = array(
205             'shortname' => 'shortname' . $number,
206             'description' => 'description' . $number,
207             'descriptionformat' => FORMAT_HTML,
208             'duedate' => 0,
209             'visible' => true,
210             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
211         );
212         $result = external::create_template($template);
213         return (object) external_api::clean_returnvalue(external::create_template_returns(), $result);
214     }
216     protected function update_template($templateid, $number) {
217         $template = array(
218             'id' => $templateid,
219             'shortname' => 'shortname' . $number,
220             'description' => 'description' . $number,
221             'descriptionformat' => FORMAT_HTML,
222             'visible' => true
223         );
224         $result = external::update_template($template);
225         return external_api::clean_returnvalue(external::update_template_returns(), $result);
226     }
228     protected function update_plan($planid, $number, $userid, $templateid, $status, $duedate) {
229         $plan = array(
230             'id' => $planid,
231             'name' => 'name' . $number,
232             'description' => 'description' . $number,
233             'descriptionformat' => FORMAT_HTML,
234             'userid' => $userid,
235             'templateid' => $templateid,
236             'status' => $status,
237             'duedate' => $duedate
238         );
239         $result = external::update_plan($plan);
240         return external_api::clean_returnvalue(external::update_plan_returns(), $result);
241     }
243     protected function update_competency_framework($id, $number = 1, $system = true) {
244         $scalepropname = 'scaleconfiguration' . $number;
245         $framework = array(
246             'id' => $id,
247             'shortname' => 'shortname' . $number,
248             'idnumber' => 'idnumber' . $number,
249             'description' => 'description' . $number,
250             'descriptionformat' => FORMAT_HTML,
251             'scaleid' => $number,
252             'scaleconfiguration' => $this->$scalepropname,
253             'visible' => true,
254             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
255         );
256         $result = external::update_competency_framework($framework);
257         return external_api::clean_returnvalue(external::update_competency_framework_returns(), $result);
258     }
260     protected function create_competency($number, $frameworkid) {
261         $competency = array(
262             'shortname' => 'shortname' . $number,
263             'idnumber' => 'idnumber' . $number,
264             'description' => 'description' . $number,
265             'descriptionformat' => FORMAT_HTML,
266             'competencyframeworkid' => $frameworkid,
267             'sortorder' => 0
268         );
269         $result = external::create_competency($competency);
270         return (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
271     }
273     protected function update_competency($id, $number) {
274         $competency = array(
275             'id' => $id,
276             'shortname' => 'shortname' . $number,
277             'idnumber' => 'idnumber' . $number,
278             'description' => 'description' . $number,
279             'descriptionformat' => FORMAT_HTML,
280             'sortorder' => 0
281         );
282         $result = external::update_competency($competency);
283         return external_api::clean_returnvalue(external::update_competency_returns(), $result);
284     }
286     /**
287      * Test we can't create a competency framework with only read permissions.
288      */
289     public function test_create_competency_frameworks_with_read_permissions() {
290         $this->setExpectedException('required_capability_exception');
291         $this->setUser($this->user);
293         $result = $this->create_competency_framework(1, true);
294     }
296     /**
297      * Test we can't create a competency framework with only read permissions.
298      */
299     public function test_create_competency_frameworks_with_read_permissions_in_category() {
300         $this->setExpectedException('required_capability_exception');
301         $this->setUser($this->catuser);
302         $result = $this->create_competency_framework(1, false);
303     }
305     /**
306      * Test we can create a competency framework with manage permissions.
307      */
308     public function test_create_competency_frameworks_with_manage_permissions() {
309         $this->setUser($this->creator);
310         $result = $this->create_competency_framework(1, true);
312         $this->assertGreaterThan(0, $result->timecreated);
313         $this->assertGreaterThan(0, $result->timemodified);
314         $this->assertEquals($this->creator->id, $result->usermodified);
315         $this->assertEquals('shortname1', $result->shortname);
316         $this->assertEquals('idnumber1', $result->idnumber);
317         $this->assertEquals('description1', $result->description);
318         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
319         $this->assertEquals(1, $result->scaleid);
320         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
321         $this->assertEquals(true, $result->visible);
322     }
324     /**
325      * Test we can create a competency framework with manage permissions.
326      */
327     public function test_create_competency_frameworks_with_manage_permissions_in_category() {
328         $this->setUser($this->catcreator);
329         $result = $this->create_competency_framework(1, false);
331         $this->assertGreaterThan(0, $result->timecreated);
332         $this->assertGreaterThan(0, $result->timemodified);
333         $this->assertEquals($this->catcreator->id, $result->usermodified);
334         $this->assertEquals('shortname1', $result->shortname);
335         $this->assertEquals('idnumber1', $result->idnumber);
336         $this->assertEquals('description1', $result->description);
337         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
338         $this->assertEquals(1, $result->scaleid);
339         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
340         $this->assertEquals(true, $result->visible);
342         try {
343             $result = $this->create_competency_framework(1, true);
344             $this->fail('User cannot create a framework at system level.');
345         } catch (required_capability_exception $e) {
346             // All good.
347         }
348     }
350     /**
351      * Test we cannot create a competency framework with nasty data.
352      */
353     public function test_create_competency_frameworks_with_nasty_data() {
354         $this->setUser($this->creator);
355         $this->setExpectedException('invalid_parameter_exception');
356         $framework = array(
357             'shortname' => 'short<a href="">',
358             'idnumber' => 'id;"number',
359             'description' => 'de<>\\..scription',
360             'descriptionformat' => FORMAT_HTML,
361             'scaleid' => 1,
362             'scaleconfiguration' => $this->scaleconfiguration1,
363             'visible' => true,
364             'contextid' => context_system::instance()->id
365         );
366         $result = external::create_competency_framework($framework);
367     }
369     /**
370      * Test we can read a competency framework with manage permissions.
371      */
372     public function test_read_competency_frameworks_with_manage_permissions() {
373         $this->setUser($this->creator);
374         $result = $this->create_competency_framework(1, true);
376         $id = $result->id;
377         $result = external::read_competency_framework($id);
378         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
380         $this->assertGreaterThan(0, $result->timecreated);
381         $this->assertGreaterThan(0, $result->timemodified);
382         $this->assertEquals($this->creator->id, $result->usermodified);
383         $this->assertEquals('shortname1', $result->shortname);
384         $this->assertEquals('idnumber1', $result->idnumber);
385         $this->assertEquals('description1', $result->description);
386         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
387         $this->assertEquals(1, $result->scaleid);
388         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
389         $this->assertEquals(true, $result->visible);
390     }
392     /**
393      * Test we can read a competency framework with manage permissions.
394      */
395     public function test_read_competency_frameworks_with_manage_permissions_in_category() {
396         $this->setUser($this->creator);
398         $insystem = $this->create_competency_framework(1, true);
399         $incat = $this->create_competency_framework(2, false);
401         $this->setUser($this->catcreator);
402         $id = $incat->id;
403         $result = external::read_competency_framework($id);
404         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
406         $this->assertGreaterThan(0, $result->timecreated);
407         $this->assertGreaterThan(0, $result->timemodified);
408         $this->assertEquals($this->creator->id, $result->usermodified);
409         $this->assertEquals('shortname2', $result->shortname);
410         $this->assertEquals('idnumber2', $result->idnumber);
411         $this->assertEquals('description2', $result->description);
412         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
413         $this->assertEquals(2, $result->scaleid);
414         $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
415         $this->assertEquals(true, $result->visible);
417         try {
418             $id = $insystem->id;
419             $result = external::read_competency_framework($id);
420             $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
421             $this->fail('User cannot read a framework at system level.');
422         } catch (required_capability_exception $e) {
423             // All good.
424         }
425     }
427     /**
428      * Test we can read a competency framework with read permissions.
429      */
430     public function test_read_competency_frameworks_with_read_permissions() {
431         $this->setUser($this->creator);
432         $result = $this->create_competency_framework(1, true);
434         // Switch users to someone with less permissions.
435         $this->setUser($this->user);
436         $id = $result->id;
437         $result = external::read_competency_framework($id);
438         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
440         $this->assertGreaterThan(0, $result->timecreated);
441         $this->assertGreaterThan(0, $result->timemodified);
442         $this->assertEquals($this->creator->id, $result->usermodified);
443         $this->assertEquals('shortname1', $result->shortname);
444         $this->assertEquals('idnumber1', $result->idnumber);
445         $this->assertEquals('description1', $result->description);
446         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
447         $this->assertEquals(1, $result->scaleid);
448         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
449         $this->assertEquals(true, $result->visible);
450     }
451     /**
452      * Test we can read a competency framework with read permissions.
453      */
454     public function test_read_competency_frameworks_with_read_permissions_in_category() {
455         $this->setUser($this->creator);
457         $insystem = $this->create_competency_framework(1, true);
458         $incat = $this->create_competency_framework(2, false);
460         // Switch users to someone with less permissions.
461         $this->setUser($this->catuser);
462         $id = $incat->id;
463         $result = external::read_competency_framework($id);
464         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
466         $this->assertGreaterThan(0, $result->timecreated);
467         $this->assertGreaterThan(0, $result->timemodified);
468         $this->assertEquals($this->creator->id, $result->usermodified);
469         $this->assertEquals('shortname2', $result->shortname);
470         $this->assertEquals('idnumber2', $result->idnumber);
471         $this->assertEquals('description2', $result->description);
472         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
473         $this->assertEquals(2, $result->scaleid);
474         $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
475         $this->assertEquals(true, $result->visible);
477         // Switching to user with no permissions.
478         try {
479             $result = external::read_competency_framework($insystem->id);
480             $this->fail('Current user cannot should not be able to read the framework.');
481         } catch (required_capability_exception $e) {
482             // All good.
483         }
484     }
486     /**
487      * Test we can delete a competency framework with manage permissions.
488      */
489     public function test_delete_competency_frameworks_with_manage_permissions() {
490         $this->setUser($this->creator);
491         $result = $this->create_competency_framework(1, true);
493         $id = $result->id;
494         $result = external::delete_competency_framework($id);
495         $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
497         $this->assertTrue($result);
498     }
500     /**
501      * Test we can delete a competency framework with manage permissions.
502      */
503     public function test_delete_competency_frameworks_with_manage_permissions_in_category() {
504         $this->setUser($this->creator);
506         $insystem = $this->create_competency_framework(1, true);
507         $incat = $this->create_competency_framework(2, false);
509         $this->setUser($this->catcreator);
510         $id = $incat->id;
511         $result = external::delete_competency_framework($id);
512         $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
514         $this->assertTrue($result);
516         try {
517             $id = $insystem->id;
518             $result = external::delete_competency_framework($id);
519             $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
520             $this->fail('Current user cannot should not be able to delete the framework.');
521         } catch (required_capability_exception $e) {
522             // All good.
523         }
524     }
526     /**
527      * Test we can delete a competency framework with read permissions.
528      */
529     public function test_delete_competency_frameworks_with_read_permissions() {
530         $this->setExpectedException('required_capability_exception');
531         $this->setUser($this->creator);
532         $result = $this->create_competency_framework(1, true);
534         $id = $result->id;
535         // Switch users to someone with less permissions.
536         $this->setUser($this->user);
537         $result = external::delete_competency_framework($id);
538     }
540     /**
541      * Test we can update a competency framework with manage permissions.
542      */
543     public function test_update_competency_frameworks_with_manage_permissions() {
544         $this->setUser($this->creator);
545         $result = $this->create_competency_framework(1, true);
547         $result = $this->update_competency_framework($result->id, 2, true);
549         $this->assertTrue($result);
550     }
552     /**
553      * Test we can update a competency framework with manage permissions.
554      */
555     public function test_update_competency_frameworks_with_manage_permissions_in_category() {
556         $this->setUser($this->creator);
558         $insystem = $this->create_competency_framework(1, true);
559         $incat = $this->create_competency_framework(2, false);
561         $this->setUser($this->catcreator);
562         $id = $incat->id;
564         $result = $this->update_competency_framework($incat->id, 3, false);
566         $this->assertTrue($result);
568         try {
569             $result = $this->update_competency_framework($insystem->id, 4, true);
570             $this->fail('Current user should not be able to update the framework.');
571         } catch (required_capability_exception $e) {
572             // All good.
573         }
574     }
576     public function test_update_framework_scale() {
577         $this->setUser($this->creator);
578         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
580         $s1 = $this->getDataGenerator()->create_scale();
582         $f1 = $lpg->create_framework(array('scaleid' => 1));
583         $f2 = $lpg->create_framework(array('scaleid' => 1));
584         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
585         $c2 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
587         $this->assertEquals(1, $f1->get_scaleid());
589         // Make the scale of f2 being used.
590         $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2->get_id()));
592         // Changing the framework where the scale is not used.
593         $result = $this->update_competency_framework($f1->get_id(), 3, true);
595         $f1 = new \core_competency\competency_framework($f1->get_id());
596         $this->assertEquals(3, $f1->get_scaleid());
598         // Changing the framework where the scale is used.
599         try {
600             $result = $this->update_competency_framework($f2->get_id(), 4, true);
601             $this->fail('The scale cannot be changed once used.');
602         } catch (\core_competency\invalid_persistent_exception $e) {
603             $this->assertRegexp('/scaleid/', $e->getMessage());
604         }
605     }
607     /**
608      * Test we can update a competency framework with read permissions.
609      */
610     public function test_update_competency_frameworks_with_read_permissions() {
611         $this->setExpectedException('required_capability_exception');
612         $this->setUser($this->creator);
613         $result = $this->create_competency_framework(1, true);
615         $this->setUser($this->user);
616         $result = $this->update_competency_framework($result->id, 2, true);
617     }
619     /**
620      * Test we can list and count competency frameworks with manage permissions.
621      */
622     public function test_list_and_count_competency_frameworks_with_manage_permissions() {
623         $this->setUser($this->creator);
624         $result = $this->create_competency_framework(1, true);
625         $result = $this->create_competency_framework(2, true);
626         $result = $this->create_competency_framework(3, true);
627         $result = $this->create_competency_framework(4, false);
629         $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
630         $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
632         $this->assertEquals($result, 3);
634         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
635             array('contextid' => context_system::instance()->id), 'self', false);
636         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
638         $this->assertEquals(count($result), 3);
639         $result = (object) $result[0];
641         $this->assertGreaterThan(0, $result->timecreated);
642         $this->assertGreaterThan(0, $result->timemodified);
643         $this->assertEquals($this->creator->id, $result->usermodified);
644         $this->assertEquals('shortname1', $result->shortname);
645         $this->assertEquals('idnumber1', $result->idnumber);
646         $this->assertEquals('description1', $result->description);
647         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
648         $this->assertEquals(1, $result->scaleid);
649         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
650         $this->assertEquals(true, $result->visible);
651     }
653     public function test_list_competency_frameworks_with_query() {
654         $this->setUser($this->creator);
655         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
656         $framework1 = $lpg->create_framework(array(
657             'shortname' => 'shortname_beetroot',
658             'idnumber' => 'idnumber_cinnamon',
659             'description' => 'description',
660             'descriptionformat' => FORMAT_HTML,
661             'visible' => true,
662             'contextid' => context_system::instance()->id
663         ));
664         $framework2 = $lpg->create_framework(array(
665             'shortname' => 'shortname_citrus',
666             'idnumber' => 'idnumber_beer',
667             'description' => 'description',
668             'descriptionformat' => FORMAT_HTML,
669             'visible' => true,
670             'contextid' => context_system::instance()->id
671         ));
673         // Search on both ID number and shortname.
674         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
675             array('contextid' => context_system::instance()->id), 'self', false, 'bee');
676         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
677         $this->assertCount(2, $result);
678         $f = (object) array_shift($result);
679         $this->assertEquals($framework1->get_id(), $f->id);
680         $f = (object) array_shift($result);
681         $this->assertEquals($framework2->get_id(), $f->id);
683         // Search on ID number.
684         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
685             array('contextid' => context_system::instance()->id), 'self', false, 'beer');
686         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
687         $this->assertCount(1, $result);
688         $f = (object) array_shift($result);
689         $this->assertEquals($framework2->get_id(), $f->id);
691         // Search on shortname.
692         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
693             array('contextid' => context_system::instance()->id), 'self', false, 'cinnamon');
694         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
695         $this->assertCount(1, $result);
696         $f = (object) array_shift($result);
697         $this->assertEquals($framework1->get_id(), $f->id);
699         // No match.
700         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
701             array('contextid' => context_system::instance()->id), 'self', false, 'pwnd!');
702         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
703         $this->assertCount(0, $result);
704     }
706     /**
707      * Test we can list and count competency frameworks with read permissions.
708      */
709     public function test_list_and_count_competency_frameworks_with_read_permissions() {
710         $this->setUser($this->creator);
711         $result = $this->create_competency_framework(1, true);
712         $result = $this->create_competency_framework(2, true);
713         $result = $this->create_competency_framework(3, true);
714         $result = $this->create_competency_framework(4, false);
716         $this->setUser($this->user);
717         $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
718         $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
719         $this->assertEquals($result, 3);
721         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
722             array('contextid' => context_system::instance()->id), 'self', false);
723         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
725         $this->assertEquals(count($result), 3);
726         $result = (object) $result[0];
728         $this->assertGreaterThan(0, $result->timecreated);
729         $this->assertGreaterThan(0, $result->timemodified);
730         $this->assertEquals($this->creator->id, $result->usermodified);
731         $this->assertEquals('shortname1', $result->shortname);
732         $this->assertEquals('idnumber1', $result->idnumber);
733         $this->assertEquals('description1', $result->description);
734         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
735         $this->assertEquals(1, $result->scaleid);
736         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
737         $this->assertEquals(true, $result->visible);
738     }
740     /**
741      * Test we can't create a competency with only read permissions.
742      */
743     public function test_create_competency_with_read_permissions() {
744         $this->setExpectedException('required_capability_exception');
745         $framework = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_framework();
746         $this->setUser($this->user);
747         $competency = $this->create_competency(1, $framework->get_id());
748     }
750     /**
751      * Test we can create a competency with manage permissions.
752      */
753     public function test_create_competency_with_manage_permissions() {
754         $this->setUser($this->creator);
755         $framework = $this->create_competency_framework(1, true);
756         $competency = $this->create_competency(1, $framework->id);
758         $this->assertGreaterThan(0, $competency->timecreated);
759         $this->assertGreaterThan(0, $competency->timemodified);
760         $this->assertEquals($this->creator->id, $competency->usermodified);
761         $this->assertEquals('shortname1', $competency->shortname);
762         $this->assertEquals('idnumber1', $competency->idnumber);
763         $this->assertEquals('description1', $competency->description);
764         $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
765         $this->assertEquals(0, $competency->parentid);
766         $this->assertEquals($framework->id, $competency->competencyframeworkid);
767     }
770     /**
771      * Test we can create a competency with manage permissions.
772      */
773     public function test_create_competency_with_manage_permissions_in_category() {
774         $this->setUser($this->creator);
776         $insystem = $this->create_competency_framework(1, true);
777         $incat = $this->create_competency_framework(2, false);
779         $this->setUser($this->catcreator);
781         $competency = $this->create_competency(1, $incat->id);
783         $this->assertGreaterThan(0, $competency->timecreated);
784         $this->assertGreaterThan(0, $competency->timemodified);
785         $this->assertEquals($this->catcreator->id, $competency->usermodified);
786         $this->assertEquals('shortname1', $competency->shortname);
787         $this->assertEquals('idnumber1', $competency->idnumber);
788         $this->assertEquals('description1', $competency->description);
789         $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
790         $this->assertEquals(0, $competency->parentid);
791         $this->assertEquals($incat->id, $competency->competencyframeworkid);
793         try {
794             $competency = $this->create_competency(2, $insystem->id);
795             $this->fail('User should not be able to create a competency in system context.');
796         } catch (required_capability_exception $e) {
797             // All good.
798         }
799     }
801     /**
802      * Test we cannot create a competency with nasty data.
803      */
804     public function test_create_competency_with_nasty_data() {
805         $this->setUser($this->creator);
806         $framework = $this->create_competency_framework(1, true);
807         $this->setExpectedException('invalid_parameter_exception');
808         $competency = array(
809             'shortname' => 'shortname<a href="">',
810             'idnumber' => 'id;"number',
811             'description' => 'de<>\\..scription',
812             'descriptionformat' => FORMAT_HTML,
813             'competencyframeworkid' => $framework->id,
814             'sortorder' => 0
815         );
816         $result = external::create_competency($competency);
817         $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
818     }
820     /**
821      * Test we can read a competency with manage permissions.
822      */
823     public function test_read_competencies_with_manage_permissions() {
824         $this->setUser($this->creator);
825         $framework = $this->create_competency_framework(1, true);
826         $competency = $this->create_competency(1, $framework->id);
828         $id = $competency->id;
829         $result = external::read_competency($id);
830         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
832         $this->assertGreaterThan(0, $result->timecreated);
833         $this->assertGreaterThan(0, $result->timemodified);
834         $this->assertEquals($this->creator->id, $result->usermodified);
835         $this->assertEquals('shortname1', $result->shortname);
836         $this->assertEquals('idnumber1', $result->idnumber);
837         $this->assertEquals('description1', $result->description);
838         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
839         $this->assertEquals(0, $result->parentid);
840         $this->assertEquals($framework->id, $result->competencyframeworkid);
841     }
843     /**
844      * Test we can read a competency with manage permissions.
845      */
846     public function test_read_competencies_with_manage_permissions_in_category() {
847         $this->setUser($this->creator);
849         $sysframework = $this->create_competency_framework(1, true);
850         $insystem = $this->create_competency(1, $sysframework->id);
852         $catframework = $this->create_competency_framework(2, false);
853         $incat = $this->create_competency(2, $catframework->id);
855         $this->setUser($this->catcreator);
856         $id = $incat->id;
857         $result = external::read_competency($id);
858         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
860         $this->assertGreaterThan(0, $result->timecreated);
861         $this->assertGreaterThan(0, $result->timemodified);
862         $this->assertEquals($this->creator->id, $result->usermodified);
863         $this->assertEquals('shortname2', $result->shortname);
864         $this->assertEquals('idnumber2', $result->idnumber);
865         $this->assertEquals('description2', $result->description);
866         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
867         $this->assertEquals(0, $result->parentid);
868         $this->assertEquals($catframework->id, $result->competencyframeworkid);
870         try {
871             external::read_competency($insystem->id);
872             $this->fail('User should not be able to read a competency in system context.');
873         } catch (required_capability_exception $e) {
874             // All good.
875         }
876     }
878     /**
879      * Test we can read a competency with read permissions.
880      */
881     public function test_read_competencies_with_read_permissions() {
882         $this->setUser($this->creator);
883         $framework = $this->create_competency_framework(1, true);
884         $competency = $this->create_competency(1, $framework->id);
886         // Switch users to someone with less permissions.
887         $this->setUser($this->user);
888         $id = $competency->id;
889         $result = external::read_competency($id);
890         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
892         $this->assertGreaterThan(0, $result->timecreated);
893         $this->assertGreaterThan(0, $result->timemodified);
894         $this->assertEquals($this->creator->id, $result->usermodified);
895         $this->assertEquals('shortname1', $result->shortname);
896         $this->assertEquals('idnumber1', $result->idnumber);
897         $this->assertEquals('description1', $result->description);
898         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
899         $this->assertEquals(0, $result->parentid);
900         $this->assertEquals($framework->id, $result->competencyframeworkid);
901     }
903     /**
904      * Test we can read a competency with read permissions.
905      */
906     public function test_read_competencies_with_read_permissions_in_category() {
907         $this->setUser($this->creator);
908         $sysframework = $this->create_competency_framework(1, true);
909         $insystem = $this->create_competency(1, $sysframework->id);
910         $catframework = $this->create_competency_framework(2, false);
911         $incat = $this->create_competency(2, $catframework->id);
913         // Switch users to someone with less permissions.
914         $this->setUser($this->catuser);
915         $id = $incat->id;
916         $result = external::read_competency($id);
917         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
919         $this->assertGreaterThan(0, $result->timecreated);
920         $this->assertGreaterThan(0, $result->timemodified);
921         $this->assertEquals($this->creator->id, $result->usermodified);
922         $this->assertEquals('shortname2', $result->shortname);
923         $this->assertEquals('idnumber2', $result->idnumber);
924         $this->assertEquals('description2', $result->description);
925         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
926         $this->assertEquals(0, $result->parentid);
927         $this->assertEquals($catframework->id, $result->competencyframeworkid);
929         try {
930             external::read_competency($insystem->id);
931             $this->fail('User should not be able to read a competency in system context.');
932         } catch (required_capability_exception $e) {
933             // All good.
934         }
935     }
937     /**
938      * Test we can delete a competency with manage permissions.
939      */
940     public function test_delete_competency_with_manage_permissions() {
941         $this->setUser($this->creator);
942         $framework = $this->create_competency_framework(1, true);
943         $result = $this->create_competency(1, $framework->id);
945         $id = $result->id;
946         $result = external::delete_competency($id);
947         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
949         $this->assertTrue($result);
950     }
952     /**
953      * Test we can delete a competency with manage permissions.
954      */
955     public function test_delete_competency_with_manage_permissions_in_category() {
956         $this->setUser($this->creator);
958         $sysframework = $this->create_competency_framework(1, true);
959         $insystem = $this->create_competency(1, $sysframework->id);
960         $catframework = $this->create_competency_framework(2, false);
961         $incat = $this->create_competency(2, $catframework->id);
963         $this->setUser($this->catcreator);
964         $id = $incat->id;
965         $result = external::delete_competency($id);
966         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
968         $this->assertTrue($result);
970         try {
971             $result = external::delete_competency($insystem->id);
972             $this->fail('User should not be able to delete a competency in system context.');
973         } catch (required_capability_exception $e) {
974             // All good.
975         }
976     }
978     /**
979      * Test we can delete a competency with read permissions.
980      */
981     public function test_delete_competency_with_read_permissions() {
982         $this->setExpectedException('required_capability_exception');
983         $this->setUser($this->creator);
984         $framework = $this->create_competency_framework(1, true);
985         $result = $this->create_competency(1, $framework->id);
987         $id = $result->id;
988         // Switch users to someone with less permissions.
989         $this->setUser($this->user);
990         $result = external::delete_competency($id);
991     }
993     /**
994      * Test we can update a competency with manage permissions.
995      */
996     public function test_update_competency_with_manage_permissions() {
997         $this->setUser($this->creator);
998         $framework = $this->create_competency_framework(1, true);
999         $result = $this->create_competency(1, $framework->id);
1001         $result = $this->update_competency($result->id, 2);
1003         $this->assertTrue($result);
1004     }
1006     /**
1007      * Test we can update a competency with manage permissions.
1008      */
1009     public function test_update_competency_with_manage_permissions_in_category() {
1010         $this->setUser($this->creator);
1012         $sysframework = $this->create_competency_framework(1, true);
1013         $insystem = $this->create_competency(1, $sysframework->id);
1014         $catframework = $this->create_competency_framework(2, false);
1015         $incat = $this->create_competency(2, $catframework->id);
1017         $this->setUser($this->catcreator);
1019         $result = $this->update_competency($incat->id, 2);
1021         $this->assertTrue($result);
1023         try {
1024             $result = $this->update_competency($insystem->id, 3);
1025             $this->fail('User should not be able to update a competency in system context.');
1026         } catch (required_capability_exception $e) {
1027             // All good.
1028         }
1029     }
1031     /**
1032      * Test we can update a competency with read permissions.
1033      */
1034     public function test_update_competency_with_read_permissions() {
1035         $this->setExpectedException('required_capability_exception');
1036         $this->setUser($this->creator);
1037         $framework = $this->create_competency_framework(1, true);
1038         $result = $this->create_competency(1, $framework->id);
1040         $this->setUser($this->user);
1041         $result = $this->update_competency($result->id, 2);
1042     }
1044     /**
1045      * Test count competencies with filters.
1046      */
1047     public function test_count_competencies_with_filters() {
1048         $this->setUser($this->creator);
1050         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1051         $f1 = $lpg->create_framework();
1052         $f2 = $lpg->create_framework();
1053         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1054         $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'shortname' => 'A'));
1055         $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1056         $c4 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1057         $c5 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1059         $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f2->get_id())));
1060         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1061         $this->assertEquals(2, $result);
1063         $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f1->get_id())));
1064         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1065         $this->assertEquals(3, $result);
1067         $result = external::count_competencies(array(array('column' => 'shortname', 'value' => 'A')));
1068         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1069         $this->assertEquals(1, $result);
1070     }
1072     /**
1073      * Test we can list and count competencies with manage permissions.
1074      */
1075     public function test_list_and_count_competencies_with_manage_permissions() {
1076         $this->setUser($this->creator);
1077         $framework = $this->create_competency_framework(1, true);
1078         $result = $this->create_competency(1, $framework->id);
1079         $result = $this->create_competency(2, $framework->id);
1080         $result = $this->create_competency(3, $framework->id);
1082         $result = external::count_competencies(array());
1083         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1085         $this->assertEquals($result, 3);
1087         array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1088         $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1090         $this->assertEquals(count($result), 3);
1091         $result = (object) $result[0];
1093         $this->assertGreaterThan(0, $result->timecreated);
1094         $this->assertGreaterThan(0, $result->timemodified);
1095         $this->assertEquals($this->creator->id, $result->usermodified);
1096         $this->assertEquals('shortname1', $result->shortname);
1097         $this->assertEquals('idnumber1', $result->idnumber);
1098         $this->assertEquals('description1', $result->description);
1099     }
1101     /**
1102      * Test we can list and count competencies with read permissions.
1103      */
1104     public function test_list_and_count_competencies_with_read_permissions() {
1105         $this->setUser($this->creator);
1106         $framework = $this->create_competency_framework(1, true);
1107         $result = $this->create_competency(1, $framework->id);
1108         $result = $this->create_competency(2, $framework->id);
1109         $result = $this->create_competency(3, $framework->id);
1111         $this->setUser($this->user);
1113         $result = external::count_competencies(array());
1114         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1116         $this->assertEquals($result, 3);
1118         array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1119         $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1121         $this->assertEquals(count($result), 3);
1122         $result = (object) $result[0];
1124         $this->assertGreaterThan(0, $result->timecreated);
1125         $this->assertGreaterThan(0, $result->timemodified);
1126         $this->assertEquals($this->creator->id, $result->usermodified);
1127         $this->assertEquals('shortname1', $result->shortname);
1128         $this->assertEquals('idnumber1', $result->idnumber);
1129         $this->assertEquals('description1', $result->description);
1130     }
1132     /**
1133      * Test we can search for competencies.
1134      */
1135     public function test_search_competencies_with_read_permissions() {
1136         $this->setUser($this->creator);
1137         $framework = $this->create_competency_framework(1, true);
1138         $result = $this->create_competency(1, $framework->id);
1139         $result = $this->create_competency(2, $framework->id);
1140         $result = $this->create_competency(3, $framework->id);
1142         $this->setUser($this->user);
1144         $result = external::search_competencies('short', $framework->id);
1145         $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
1147         $this->assertEquals(count($result), 3);
1148         $result = (object) $result[0];
1150         $this->assertGreaterThan(0, $result->timecreated);
1151         $this->assertGreaterThan(0, $result->timemodified);
1152         $this->assertEquals($this->creator->id, $result->usermodified);
1153         $this->assertEquals('shortname1', $result->shortname);
1154         $this->assertEquals('idnumber1', $result->idnumber);
1155         $this->assertEquals('description1', $result->description);
1156     }
1158     /**
1159      * Test plans creation and updates.
1160      */
1161     public function test_create_and_update_plans() {
1162         $syscontext = context_system::instance();
1164         $this->setUser($this->creator);
1165         $plan0 = $this->create_plan(1, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1167         $this->setUser($this->user);
1169         try {
1170             $plan1 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1171             $this->fail('Exception expected due to not permissions to create draft plans');
1172         } catch (moodle_exception $e) {
1173             $this->assertEquals('nopermissions', $e->errorcode);
1174         }
1176         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1177         accesslib_clear_all_caches_for_unit_testing();
1179         $this->setUser($this->user);
1181         $plan2 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1183         try {
1184             $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1185             $this->fail('Exception expected due to not permissions to create active plans');
1186         } catch (moodle_exception $e) {
1187             $this->assertEquals('nopermissions', $e->errorcode);
1188         }
1189         try {
1190             $plan3 = $this->update_plan($plan2->id, 4, $this->user->id, 0, plan::STATUS_COMPLETE, 0);
1191             $this->fail('We cannot complete a plan using api::update_plan().');
1192         } catch (coding_exception $e) {
1193             $this->assertTrue(true);
1194         }
1196         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1197         accesslib_clear_all_caches_for_unit_testing();
1199         $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1200         try {
1201             $plan4 = $this->create_plan(6, $this->creator->id, 0, plan::STATUS_COMPLETE, 0);
1202             $this->fail('Plans cannot be created as complete.');
1203         } catch (coding_exception $e) {
1204             $this->assertRegexp('/A plan cannot be created as complete./', $e->getMessage());
1205         }
1207         try {
1208             $plan0 = $this->update_plan($plan0->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1209         } catch (moodle_exception $e) {
1210             $this->assertEquals('nopermissions', $e->errorcode);
1211         }
1213         unassign_capability('moodle/competency:planmanageown', $this->userrole, $syscontext->id);
1214         unassign_capability('moodle/competency:planmanageowndraft', $this->userrole, $syscontext->id);
1215         accesslib_clear_all_caches_for_unit_testing();
1217         try {
1218             // Cannot be updated even if they created it.
1219             $this->update_plan($plan2->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1220             $this->fail('The user can not update their own plan without permissions.');
1221         } catch (required_capability_exception $e) {
1222             $this->assertRegexp('/Manage learning plans./', $e->getMessage());
1223         }
1224     }
1226     /**
1227      * Test complete plan.
1228      */
1229     public function test_complete_plan() {
1230         $syscontext = context_system::instance();
1232         $this->setUser($this->creator);
1234         $this->setUser($this->user);
1236         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1237         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1238         accesslib_clear_all_caches_for_unit_testing();
1240         $this->setUser($this->user);
1242         $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1244         $result = external::complete_plan($plan->id);
1245         $this->assertTrue($result);
1246     }
1248     /**
1249      * Test reopen plan.
1250      */
1251     public function test_reopen_plan() {
1252         $syscontext = context_system::instance();
1254         $this->setUser($this->creator);
1256         $this->setUser($this->user);
1258         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1259         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1260         accesslib_clear_all_caches_for_unit_testing();
1262         $this->setUser($this->user);
1264         $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1265         external::complete_plan($plan->id);
1267         $result = external::reopen_plan($plan->id);
1268         $this->assertTrue($result);
1269     }
1271     /**
1272      * Test that we can read plans.
1273      */
1274     public function test_read_plans() {
1275         global $OUTPUT;
1276         $this->setUser($this->creator);
1278         $syscontext = context_system::instance();
1280         $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1281         $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1282         $plan3 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1283         external::complete_plan($plan3->id);
1284         $plan3 = (object) external::read_plan($plan3->id);
1286         $data = external::read_plan($plan1->id);
1287         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1288         $data = external::read_plan($plan2->id);
1289         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1290         $data = external::read_plan($plan3->id);
1291         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1293         $this->setUser($this->user);
1295         // The normal user can not edit these plans.
1296         $plan1->canmanage = false;
1297         $plan2->canmanage = false;
1298         $plan3->canmanage = false;
1299         $plan1->canbeedited = false;
1300         $plan2->canbeedited = false;
1301         $plan3->canbeedited = false;
1302         $plan1->canrequestreview = true;
1303         $plan2->canrequestreview = true;
1304         $plan3->canrequestreview = true;
1305         $plan1->canreview = false;
1306         $plan2->canreview = false;
1307         $plan3->canreview = false;
1308         $plan1->iscompleteallowed = false;
1309         $plan2->iscompleteallowed = false;
1310         $plan3->iscompleteallowed = false;
1311         $plan1->isrequestreviewallowed = true;
1312         $plan2->isrequestreviewallowed = true;
1313         $plan3->isrequestreviewallowed = true;
1314         $plan1->isapproveallowed = false;
1315         $plan2->isapproveallowed = false;
1316         $plan3->isapproveallowed = false;
1317         $plan1->isunapproveallowed = false;
1318         $plan2->isunapproveallowed = false;
1319         $plan3->isunapproveallowed = false;
1320         $plan3->isreopenallowed = false;
1321         $plan1->commentarea['canpost'] = false;
1322         $plan1->commentarea['canview'] = true;
1324         // Prevent the user from seeing their own non-draft plans.
1325         assign_capability('moodle/competency:plancommentown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1326         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1327         assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1328         accesslib_clear_all_caches_for_unit_testing();
1330         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1332         try {
1333             external::read_plan($plan2->id);
1334             $this->fail('Exception expected due to not permissions to read plan');
1335         } catch (moodle_exception $e) {
1336             $this->assertEquals('nopermissions', $e->errorcode);
1337         }
1338         try {
1339             external::read_plan($plan3->id);
1340             $this->fail('Exception expected due to not permissions to read plan');
1341         } catch (moodle_exception $e) {
1342             $this->assertEquals('nopermissions', $e->errorcode);
1343         }
1345         // Allow user to see their plan.
1346         assign_capability('moodle/competency:plancommentown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1347         assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1348         assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1349         accesslib_clear_all_caches_for_unit_testing();
1351         $plan1->commentarea['canpost'] = true;
1352         $plan1->commentarea['canview'] = true;
1353         $plan2->commentarea['canpost'] = true;
1354         $plan2->isrequestreviewallowed = false;
1355         $plan3->commentarea['canpost'] = true;
1356         $plan3->isrequestreviewallowed = false;
1357         $plan1->commentarea['canpostorhascomments'] = true;
1358         $plan2->commentarea['canpostorhascomments'] = true;
1359         $plan3->commentarea['canpostorhascomments'] = true;
1361         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1362         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1363         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1365         // Allow use to manage their own draft plan.
1366         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1367         assign_capability('moodle/competency:planmanageown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1368         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1369         accesslib_clear_all_caches_for_unit_testing();
1371         $plan1->canmanage = true;
1372         $plan1->canbeedited = true;
1373         $plan1->canrequestreview = true;
1374         $plan1->isrequestreviewallowed = true;
1375         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1376         try {
1377             external::read_plan($plan2->id);
1378             $this->fail('Exception expected due to not permissions to read plan');
1379         } catch (moodle_exception $e) {
1380             $this->assertEquals('nopermissions', $e->errorcode);
1381         }
1382         try {
1383             external::read_plan($plan3->id);
1384             $this->fail('Exception expected due to not permissions to read plan');
1385         } catch (moodle_exception $e) {
1386             $this->assertEquals('nopermissions', $e->errorcode);
1387         }
1389         // Allow use to manage their plan.
1390         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1391         assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1392         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1393         accesslib_clear_all_caches_for_unit_testing();
1395         $plan1->canmanage = false;
1396         $plan1->canbeedited = false;
1397         $plan1->canrequestreview = true;
1398         $plan1->canreview = true;
1399         $plan1->isrequestreviewallowed = true;
1400         $plan1->isapproveallowed = true;
1401         $plan1->iscompleteallowed = false;
1403         $plan2->canmanage = true;
1404         $plan2->canbeedited = true;
1405         $plan2->canreview = true;
1406         $plan2->iscompleteallowed = true;
1407         $plan2->isunapproveallowed = true;
1409         $plan3->canmanage = true;
1410         $plan3->canreview = true;
1411         $plan3->isreopenallowed = true;
1413         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1414         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1415         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1416     }
1418     public function test_delete_plans() {
1419         $this->setUser($this->creator);
1421         $syscontext = context_system::instance();
1423         $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1424         $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1425         $plan3 = $this->create_plan(3, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1427         $this->assertTrue(external::delete_plan($plan1->id));
1429         unassign_capability('moodle/competency:planmanage', $this->creatorrole, $syscontext->id);
1430         accesslib_clear_all_caches_for_unit_testing();
1432         try {
1433             external::delete_plan($plan2->id);
1434             $this->fail('Exception expected due to not permissions to manage plans');
1435         } catch (moodle_exception $e) {
1436             $this->assertEquals('nopermissions', $e->errorcode);
1437         }
1439         $this->setUser($this->user);
1441         // Can not delete plans created by other users.
1442         try {
1443             external::delete_plan($plan2->id);
1444             $this->fail('Exception expected due to not permissions to manage plans');
1445         } catch (moodle_exception $e) {
1446             $this->assertEquals('nopermissions', $e->errorcode);
1447         }
1449         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1450         accesslib_clear_all_caches_for_unit_testing();
1452         $this->assertTrue(external::delete_plan($plan2->id));
1454         // Can not delete plans created for other users.
1455         try {
1456             external::delete_plan($plan3->id);
1457             $this->fail('Exception expected due to not permissions to manage plans');
1458         } catch (moodle_exception $e) {
1459             $this->assertEquals('nopermissions', $e->errorcode);
1460         }
1462         $plan4 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1463         $this->assertTrue(external::delete_plan($plan4->id));
1464     }
1466     public function test_delete_plan_removes_relations() {
1467         $this->setAdminUser();
1468         $dg = $this->getDataGenerator();
1469         $lpg = $dg->get_plugin_generator('core_competency');
1471         $user = $dg->create_user();
1472         $plan = $lpg->create_plan(array('userid' => $user->id));
1473         $framework = $lpg->create_framework();
1474         $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1475         $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1476         $comp3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1477         $pc1 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp1->get_id()));
1478         $pc2 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp2->get_id()));
1479         $pc3 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp3->get_id()));
1481         // Complete the plan to generate user_competency_plan entries.
1482         api::complete_plan($plan);
1484         // Confirm the data we have.
1485         $this->assertEquals(3, plan_competency::count_records(array('planid' => $plan->get_id())));
1486         $this->assertEquals(3, user_competency_plan::count_records(array('planid' => $plan->get_id(), 'userid' => $user->id)));
1488         // Delete the plan now.
1489         api::delete_plan($plan->get_id());
1490         $this->assertEquals(0, plan_competency::count_records(array('planid' => $plan->get_id())));
1491         $this->assertEquals(0, user_competency_plan::count_records(array('planid' => $plan->get_id(), 'userid' => $user->id)));
1492     }
1494     public function test_list_plan_competencies() {
1495         $this->setUser($this->creator);
1497         $dg = $this->getDataGenerator();
1498         $lpg = $dg->get_plugin_generator('core_competency');
1500         $f1 = $lpg->create_framework();
1501         $f2 = $lpg->create_framework();
1503         $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1504         $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1505         $c1c = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1506         $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1507         $c2b = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1509         $tpl = $lpg->create_template();
1510         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1a->get_id()));
1511         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1c->get_id()));
1512         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2b->get_id()));
1514         $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id()));
1516         $uc1a = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1a->get_id(),
1517             'status' => user_competency::STATUS_IN_REVIEW, 'reviewerid' => $this->creator->id));
1518         $uc1b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1b->get_id()));
1519         $uc2b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2b->get_id(),
1520             'grade' => 2, 'proficiency' => 1));
1521         $ux1a = $lpg->create_user_competency(array('userid' => $this->creator->id, 'competencyid' => $c1a->get_id()));
1523         $result = external::list_plan_competencies($plan->get_id());
1524         $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1526         $this->assertCount(3, $result);
1527         $this->assertEquals($c1a->get_id(), $result[0]['competency']['id']);
1528         $this->assertEquals($this->user->id, $result[0]['usercompetency']['userid']);
1529         $this->assertArrayNotHasKey('usercompetencyplan', $result[0]);
1530         $this->assertEquals($c1c->get_id(), $result[1]['competency']['id']);
1531         $this->assertEquals($this->user->id, $result[1]['usercompetency']['userid']);
1532         $this->assertArrayNotHasKey('usercompetencyplan', $result[1]);
1533         $this->assertEquals($c2b->get_id(), $result[2]['competency']['id']);
1534         $this->assertEquals($this->user->id, $result[2]['usercompetency']['userid']);
1535         $this->assertArrayNotHasKey('usercompetencyplan', $result[2]);
1536         $this->assertEquals(user_competency::STATUS_IN_REVIEW, $result[0]['usercompetency']['status']);
1537         $this->assertEquals(null, $result[1]['usercompetency']['grade']);
1538         $this->assertEquals(2, $result[2]['usercompetency']['grade']);
1539         $this->assertEquals(1, $result[2]['usercompetency']['proficiency']);
1541         // Check the return values when the plan status is complete.
1542         $completedplan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id(),
1543                 'status' => plan::STATUS_COMPLETE));
1545         $uc1a = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1a->get_id(),
1546                 'planid' => $completedplan->get_id()));
1547         $uc1b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1c->get_id(),
1548                 'planid' => $completedplan->get_id()));
1549         $uc2b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c2b->get_id(),
1550                 'planid' => $completedplan->get_id(), 'grade' => 2, 'proficiency' => 1));
1551         $ux1a = $lpg->create_user_competency_plan(array('userid' => $this->creator->id, 'competencyid' => $c1a->get_id(),
1552                 'planid' => $completedplan->get_id()));
1554         $result = external::list_plan_competencies($completedplan->get_id());
1555         $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1557         $this->assertCount(3, $result);
1558         $this->assertEquals($c1a->get_id(), $result[0]['competency']['id']);
1559         $this->assertEquals($this->user->id, $result[0]['usercompetencyplan']['userid']);
1560         $this->assertArrayNotHasKey('usercompetency', $result[0]);
1561         $this->assertEquals($c1c->get_id(), $result[1]['competency']['id']);
1562         $this->assertEquals($this->user->id, $result[1]['usercompetencyplan']['userid']);
1563         $this->assertArrayNotHasKey('usercompetency', $result[1]);
1564         $this->assertEquals($c2b->get_id(), $result[2]['competency']['id']);
1565         $this->assertEquals($this->user->id, $result[2]['usercompetencyplan']['userid']);
1566         $this->assertArrayNotHasKey('usercompetency', $result[2]);
1567         $this->assertEquals(null, $result[1]['usercompetencyplan']['grade']);
1568         $this->assertEquals(2, $result[2]['usercompetencyplan']['grade']);
1569         $this->assertEquals(1, $result[2]['usercompetencyplan']['proficiency']);
1570     }
1572     public function test_add_competency_to_template() {
1573         $this->setUser($this->creator);
1575         $syscontext = context_system::instance();
1577         // Create a template.
1578         $template = $this->create_template(1, true);
1580         // Create a competency.
1581         $framework = $this->create_competency_framework(1, true);
1582         $competency = $this->create_competency(1, $framework->id);
1584         // Add the competency.
1585         external::add_competency_to_template($template->id, $competency->id);
1587         // Check that it was added.
1588         $this->assertEquals(1, external::count_competencies_in_template($template->id));
1590         // Unassign capability.
1591         unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1592         accesslib_clear_all_caches_for_unit_testing();
1594         // Check we can not add the competency now.
1595         try {
1596             external::add_competency_to_template($template->id, $competency->id);
1597             $this->fail('Exception expected due to not permissions to manage template competencies');
1598         } catch (moodle_exception $e) {
1599             $this->assertEquals('nopermissions', $e->errorcode);
1600         }
1601     }
1603     public function test_remove_competency_from_template() {
1604         $syscontext = context_system::instance();
1605         $this->setUser($this->creator);
1606         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1608         // Create a template.
1609         $template = $this->create_template(1, true);
1611         // Create a competency.
1612         $framework = $lpg->create_framework();
1613         $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1615         // Add the competency.
1616         external::add_competency_to_template($template->id, $competency->get_id());
1618         // Check that it was added.
1619         $this->assertEquals(1, external::count_competencies_in_template($template->id));
1621         // Check that we can remove the competency.
1622         external::remove_competency_from_template($template->id, $competency->get_id());
1624         // Check that it was removed.
1625         $this->assertEquals(0, external::count_competencies_in_template($template->id));
1627         // Unassign capability.
1628         unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1629         accesslib_clear_all_caches_for_unit_testing();
1631         // Check we can not remove the competency now.
1632         try {
1633             external::add_competency_to_template($template->id, $competency->get_id());
1634             $this->fail('Exception expected due to not permissions to manage template competencies');
1635         } catch (moodle_exception $e) {
1636             $this->assertEquals('nopermissions', $e->errorcode);
1637         }
1638     }
1640     /**
1641      * Test we can re-order competency frameworks.
1642      */
1643     public function test_reorder_template_competencies() {
1644         $this->setUser($this->creator);
1646         $syscontext = context_system::instance();
1647         $onehour = time() + 60 * 60;
1649         // Create a template.
1650         $template = $this->create_template(1, true);
1652         // Create a competency framework.
1653         $framework = $this->create_competency_framework(1, true);
1655         // Create multiple competencies.
1656         $competency1 = $this->create_competency(1, $framework->id);
1657         $competency2 = $this->create_competency(2, $framework->id);
1658         $competency3 = $this->create_competency(3, $framework->id);
1659         $competency4 = $this->create_competency(4, $framework->id);
1661         // Add the competencies.
1662         external::add_competency_to_template($template->id, $competency1->id);
1663         external::add_competency_to_template($template->id, $competency2->id);
1664         external::add_competency_to_template($template->id, $competency3->id);
1665         external::add_competency_to_template($template->id, $competency4->id);
1667         // Test if removing competency from template don't create sortorder holes.
1668         external::remove_competency_from_template($template->id, $competency3->id);
1669         $templcomp4 = template_competency::get_record(array(
1670             'templateid' => $template->id,
1671             'competencyid' => $competency4->id
1672         ));
1674         $this->assertEquals(2, $templcomp4->get_sortorder());
1676         // This is a move up.
1677         external::reorder_template_competency($template->id, $competency4->id, $competency2->id);
1678         $result = external::list_competencies_in_template($template->id);
1679         $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1681         $r1 = (object) $result[0];
1682         $r2 = (object) $result[1];
1683         $r3 = (object) $result[2];
1685         $this->assertEquals($competency1->id, $r1->id);
1686         $this->assertEquals($competency4->id, $r2->id);
1687         $this->assertEquals($competency2->id, $r3->id);
1689         // This is a move down.
1690         external::reorder_template_competency($template->id, $competency1->id, $competency4->id);
1691         $result = external::list_competencies_in_template($template->id);
1692         $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1694         $r1 = (object) $result[0];
1695         $r2 = (object) $result[1];
1696         $r3 = (object) $result[2];
1698         $this->assertEquals($competency4->id, $r1->id);
1699         $this->assertEquals($competency1->id, $r2->id);
1700         $this->assertEquals($competency2->id, $r3->id);
1702         $this->setExpectedException('required_capability_exception');
1703         $this->setUser($this->user);
1704         external::reorder_template_competency($template->id, $competency1->id, $competency2->id);
1705     }
1707     /**
1708      * Test we can duplicate learning plan template.
1709      */
1710     public function test_duplicate_learning_plan_template() {
1711         $this->setUser($this->creator);
1713         $syscontext = context_system::instance();
1714         $onehour = time() + 60 * 60;
1716         // Create a template.
1717         $template = $this->create_template(1, true);
1719         // Create a competency framework.
1720         $framework = $this->create_competency_framework(1, true);
1722         // Create multiple competencies.
1723         $competency1 = $this->create_competency(1, $framework->id);
1724         $competency2 = $this->create_competency(2, $framework->id);
1725         $competency3 = $this->create_competency(3, $framework->id);
1727         // Add the competencies.
1728         external::add_competency_to_template($template->id, $competency1->id);
1729         external::add_competency_to_template($template->id, $competency2->id);
1730         external::add_competency_to_template($template->id, $competency3->id);
1732         // Duplicate the learning plan template.
1733         $duplicatedtemplate = external::duplicate_template($template->id);
1735         $result = external::list_competencies_in_template($template->id);
1736         $resultduplicated = external::list_competencies_in_template($duplicatedtemplate->id);
1738         $this->assertEquals(count($result), count($resultduplicated));
1739         $this->assertContains($template->shortname, $duplicatedtemplate->shortname);
1740         $this->assertEquals($duplicatedtemplate->description, $template->description);
1741         $this->assertEquals($duplicatedtemplate->descriptionformat, $template->descriptionformat);
1742         $this->assertEquals($duplicatedtemplate->visible, $template->visible);
1743     }
1745     /**
1746      * Test that we can return scale values for a scale with the scale ID.
1747      */
1748     public function test_get_scale_values() {
1749         global $DB;
1751         $this->setUser($this->creator);
1753         // Create a scale.
1754         $record = new stdClass();
1755         $record->courseid = 0;
1756         $record->userid = $this->creator->id;
1757         $record->name = 'Test scale';
1758         $record->scale = 'Poor, Not good, Okay, Fine, Excellent';
1759         $record->description = '<p>Test scale description.</p>';
1760         $record->descriptionformat = 1;
1761         $record->timemodified = time();
1762         $scaleid = $DB->insert_record('scale', $record);
1763         // Expected return value.
1764         $expected = array(array(
1765                 'id' => 1,
1766                 'name' => 'Poor'
1767             ), array(
1768                 'id' => 2,
1769                 'name' => 'Not good'
1770             ), array(
1771                 'id' => 3,
1772                 'name' => 'Okay'
1773             ), array(
1774                 'id' => 4,
1775                 'name' => 'Fine'
1776             ), array(
1777                 'id' => 5,
1778                 'name' => 'Excellent'
1779             )
1780         );
1781         // Call the webservice.
1782         $result = external::get_scale_values($scaleid);
1783         $this->assertEquals($expected, $result);
1784     }
1786     /**
1787      * Create a template.
1788      */
1789     public function test_create_template() {
1790         $syscontextid = context_system::instance()->id;
1791         $catcontextid = context_coursecat::instance($this->category->id)->id;
1793         // A user without permission.
1794         $this->setUser($this->user);
1795         try {
1796             $result = $this->create_template(1, true);
1797             $this->fail('Invalid permissions');
1798         } catch (required_capability_exception $e) {
1799             // All good.
1800         }
1802         // A user without permission in a category.
1803         $this->setUser($this->catuser);
1804         try {
1805             $result = $this->create_template(1, false);
1806             $this->fail('Invalid permissions');
1807         } catch (required_capability_exception $e) {
1808             // All good.
1809         }
1811         // A user with permissions in the system.
1812         $this->setUser($this->creator);
1813         $result = $this->create_template(1, true);
1814         $this->assertEquals('shortname1', $result->shortname);
1815         $this->assertEquals($syscontextid, $result->contextid);
1816         $this->assertNotEmpty($result->id);
1818         $result = $this->create_template(2, false);
1819         $this->assertEquals('shortname2', $result->shortname);
1820         $this->assertEquals($catcontextid, $result->contextid);
1821         $this->assertNotEmpty($result->id);
1823         // A user with permissions in the category.
1824         $this->setUser($this->catcreator);
1825         try {
1826             $result = $this->create_template(3, true);
1827             $this->fail('Invalid permissions');
1828         } catch (required_capability_exception $e) {
1829             // All good.
1830         }
1832         $result = $this->create_template(3, false);
1833         $this->assertEquals('shortname3', $result->shortname);
1834         $this->assertEquals($catcontextid, $result->contextid);
1835         $this->assertNotEmpty($result->id);
1836     }
1838     /**
1839      * Read a template.
1840      */
1841     public function test_read_template() {
1842         $syscontextid = context_system::instance()->id;
1843         $catcontextid = context_coursecat::instance($this->category->id)->id;
1845         // Set a due date for the next year.
1846         $date = new DateTime('now');
1847         $date->modify('+1 year');
1848         $duedate = $date->getTimestamp();
1850         // Creating two templates.
1851         $this->setUser($this->creator);
1852         $systemplate = $this->create_template(1, true);
1853         $cattemplate = $this->create_template(2, false);
1855         // User without permissions to read in system.
1856         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
1857         accesslib_clear_all_caches_for_unit_testing();
1858         $this->setUser($this->user);
1859         $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1860         try {
1861             external::read_template($systemplate->id);
1862             $this->fail('Invalid permissions');
1863         } catch (required_capability_exception $e) {
1864             // All good.
1865         }
1866         try {
1867             external::read_template($cattemplate->id);
1868             $this->fail('Invalid permissions');
1869         } catch (required_capability_exception $e) {
1870             // All good.
1871         }
1873         // User with permissions to read in a category.
1874         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
1875         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
1876         accesslib_clear_all_caches_for_unit_testing();
1877         $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1878         $this->assertTrue(has_capability('moodle/competency:templateview', context_coursecat::instance($this->category->id)));
1879         try {
1880             external::read_template($systemplate->id);
1881             $this->fail('Invalid permissions');
1882         } catch (required_capability_exception $e) {
1883             // All good.
1884         }
1886         $result = external::read_template($cattemplate->id);
1887         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1888         $this->assertEquals($cattemplate->id, $result['id']);
1889         $this->assertEquals('shortname2', $result['shortname']);
1890         $this->assertEquals('description2', $result['description']);
1891         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1892         $this->assertEquals(1, $result['visible']);
1893         $this->assertEquals(0, $result['duedate']);
1894         $this->assertEquals(userdate(0), $result['duedateformatted']);
1896         // User with permissions to read in the system.
1897         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
1898         accesslib_clear_all_caches_for_unit_testing();
1899         $this->assertTrue(has_capability('moodle/competency:templateview', context_system::instance()));
1900         $result = external::read_template($systemplate->id);
1901         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1902         $this->assertEquals($systemplate->id, $result['id']);
1903         $this->assertEquals('shortname1', $result['shortname']);
1904         $this->assertEquals('description1', $result['description']);
1905         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1906         $this->assertEquals(true, $result['visible']);
1907         $this->assertEquals(0, $result['duedate']);
1908         $this->assertEquals(userdate(0), $result['duedateformatted']);
1910         $result = external::read_template($cattemplate->id);
1911         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1912         $this->assertEquals($cattemplate->id, $result['id']);
1913         $this->assertEquals('shortname2', $result['shortname']);
1914         $this->assertEquals('description2', $result['description']);
1915         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1916         $this->assertEquals(true, $result['visible']);
1917         $this->assertEquals(0, $result['duedate']);
1918         $this->assertEquals(userdate(0), $result['duedateformatted']);
1919     }
1921     /**
1922      * Update a template.
1923      */
1924     public function test_update_template() {
1925         $syscontextid = context_system::instance()->id;
1926         $catcontextid = context_coursecat::instance($this->category->id)->id;
1928         // Set a due date for the next year.
1929         $date = new DateTime('now');
1930         $date->modify('+1 year');
1931         $duedate = $date->getTimestamp();
1933         // Creating two templates.
1934         $this->setUser($this->creator);
1935         $systemplate = $this->create_template(1, true);
1936         $cattemplate = $this->create_template(2, false);
1938         // Trying to update in a without permissions.
1939         $this->setUser($this->user);
1940         try {
1941             $this->update_template($systemplate->id, 3);
1942             $this->fail('Invalid permissions');
1943         } catch (required_capability_exception $e) {
1944             // All good.
1945         }
1947         try {
1948             $this->update_template($cattemplate->id, 3);
1949             $this->fail('Invalid permissions');
1950         } catch (required_capability_exception $e) {
1951             // All good.
1952         }
1954         // User with permissions to update in category.
1955         $this->setUser($this->catcreator);
1956         try {
1957             $this->update_template($systemplate->id, 3);
1958             $this->fail('Invalid permissions');
1959         } catch (required_capability_exception $e) {
1960             // All good.
1961         }
1963         $result = $this->update_template($cattemplate->id, 3);
1964         $this->assertTrue($result);
1965         $result = external::read_template($cattemplate->id);
1966         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1967         $this->assertEquals($cattemplate->id, $result['id']);
1968         $this->assertEquals('shortname3', $result['shortname']);
1969         $this->assertEquals("description3", $result['description']);
1970         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1971         $this->assertEquals(true, $result['visible']);
1972         $this->assertEquals(0, $result['duedate']);
1973         $this->assertEquals(userdate(0), $result['duedateformatted']);
1975         // User with permissions to update in the system.
1976         $this->setUser($this->creator);
1977         $result = $this->update_template($systemplate->id, 4);
1978         $this->assertTrue($result);
1979         $result = external::read_template($systemplate->id);
1980         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1981         $this->assertEquals($systemplate->id, $result['id']);
1982         $this->assertEquals('shortname4', $result['shortname']);
1983         $this->assertEquals('description4', $result['description']);
1984         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1985         $this->assertEquals(true, $result['visible']);
1986         $this->assertEquals(0, $result['duedate']);
1987         $this->assertEquals(userdate(0), $result['duedateformatted']);
1989         $result = $this->update_template($cattemplate->id, 5);
1990         $this->assertTrue($result);
1991         $result = external::read_template($cattemplate->id);
1992         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1993         $this->assertEquals($cattemplate->id, $result['id']);
1994         $this->assertEquals('shortname5', $result['shortname']);
1995         $this->assertEquals('description5', $result['description']);
1996         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1997         $this->assertEquals(1, $result['visible']);
1998         $this->assertEquals(0, $result['duedate']);
1999         $this->assertEquals(userdate(0), $result['duedateformatted']);
2000     }
2002     /**
2003      * Delete a template.
2004      */
2005     public function test_delete_template() {
2006         global $DB;
2007         $syscontextid = context_system::instance()->id;
2008         $catcontextid = context_coursecat::instance($this->category->id)->id;
2010         // Creating a few templates.
2011         $this->setUser($this->creator);
2012         $sys1 = $this->create_template(1, true);
2013         $cat1 = $this->create_template(2, false);
2014         $cat2 = $this->create_template(3, false);
2015         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2016         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2017         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2019         // User without permissions.
2020         $this->setUser($this->user);
2021         try {
2022             external::delete_template($sys1->id);
2023             $this->fail('Invalid permissions');
2024         } catch (required_capability_exception $e) {
2025             // All good.
2026         }
2027         try {
2028             external::delete_template($cat1->id);
2029             $this->fail('Invalid permissions');
2030         } catch (required_capability_exception $e) {
2031             // All good.
2032         }
2034         // User with category permissions.
2035         $this->setUser($this->catcreator);
2036         try {
2037             external::delete_template($sys1->id);
2038             $this->fail('Invalid permissions');
2039         } catch (required_capability_exception $e) {
2040             // All good.
2041         }
2043         $result = external::delete_template($cat1->id);
2044         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2045         $this->assertTrue($result);
2046         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2048         // User with system permissions.
2049         $this->setUser($this->creator);
2050         $result = external::delete_template($sys1->id);
2051         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2052         $this->assertTrue($result);
2053         $result = external::delete_template($cat2->id);
2054         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2055         $this->assertTrue($result);
2056         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2057         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2058     }
2060     /**
2061      * List templates.
2062      */
2063     public function test_list_templates() {
2064         $syscontextid = context_system::instance()->id;
2065         $catcontextid = context_coursecat::instance($this->category->id)->id;
2067         // Creating a few templates.
2068         $this->setUser($this->creator);
2069         $sys1 = $this->create_template(1, true);
2070         $sys2 = $this->create_template(2, true);
2071         $cat1 = $this->create_template(3, false);
2072         $cat2 = $this->create_template(4, false);
2074         // User without permission.
2075         $this->setUser($this->user);
2076         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2077         accesslib_clear_all_caches_for_unit_testing();
2078         try {
2079             external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2080             $this->fail('Invalid permissions');
2081         } catch (required_capability_exception $e) {
2082             // All good.
2083         }
2085         // User with category permissions.
2086         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2087         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2088         accesslib_clear_all_caches_for_unit_testing();
2089         $result = external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2090         $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2091         $this->assertCount(2, $result);
2092         $this->assertEquals($cat1->id, $result[0]['id']);
2093         $this->assertEquals($cat2->id, $result[1]['id']);
2095         // User with system permissions.
2096         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2097         accesslib_clear_all_caches_for_unit_testing();
2098         $result = external::list_templates('id', 'DESC', 0, 3, array('contextid' => $catcontextid), 'parents', false);
2099         $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2100         $this->assertCount(3, $result);
2101         $this->assertEquals($cat2->id, $result[0]['id']);
2102         $this->assertEquals($cat1->id, $result[1]['id']);
2103         $this->assertEquals($sys2->id, $result[2]['id']);
2104     }
2106     /**
2107      * List templates using competency.
2108      */
2109     public function test_list_templates_using_competency() {
2110         $this->setUser($this->creator);
2112         // Create a template.
2113         $template1 = $this->create_template(1, true);
2114         $template2 = $this->create_template(2, true);
2115         $template3 = $this->create_template(3, true);
2116         $template4 = $this->create_template(4, true);
2118         // Create a competency.
2119         $framework = $this->create_competency_framework(1, true);
2120         $competency1 = $this->create_competency(1, $framework->id);
2121         $competency2 = $this->create_competency(2, $framework->id);
2123         // Add the competency.
2124         external::add_competency_to_template($template1->id, $competency1->id);
2125         external::add_competency_to_template($template2->id, $competency1->id);
2126         external::add_competency_to_template($template3->id, $competency1->id);
2128         external::add_competency_to_template($template4->id, $competency2->id);
2130         $listcomp1 = external::list_templates_using_competency($competency1->id);
2131         $listcomp2 = external::list_templates_using_competency($competency2->id);
2133         // Test count_templates_using_competency.
2134         $counttempcomp1 = external::count_templates_using_competency($competency1->id);
2135         $counttempcomp2 = external::count_templates_using_competency($competency2->id);
2137         $comptemp1 = $listcomp1[0];
2138         $comptemp2 = $listcomp1[1];
2139         $comptemp3 = $listcomp1[2];
2141         $comptemp4 = $listcomp2[0];
2143         $this->assertCount(3, $listcomp1);
2144         $this->assertCount(1, $listcomp2);
2145         $this->assertEquals(3, $counttempcomp1);
2146         $this->assertEquals(1, $counttempcomp2);
2147         $this->assertEquals($template1->id, $comptemp1->id);
2148         $this->assertEquals($template2->id, $comptemp2->id);
2149         $this->assertEquals($template3->id, $comptemp3->id);
2150         $this->assertEquals($template4->id, $comptemp4->id);
2151     }
2153     public function test_count_templates() {
2154         $syscontextid = context_system::instance()->id;
2155         $catcontextid = context_coursecat::instance($this->category->id)->id;
2157         // Creating a few templates.
2158         $this->setUser($this->creator);
2159         $sys1 = $this->create_template(1, true);
2160         $sys2 = $this->create_template(2, true);
2161         $cat1 = $this->create_template(3, false);
2162         $cat2 = $this->create_template(4, false);
2163         $cat3 = $this->create_template(5, false);
2165         // User without permission.
2166         $this->setUser($this->user);
2167         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2168         accesslib_clear_all_caches_for_unit_testing();
2169         try {
2170             external::count_templates(array('contextid' => $syscontextid), 'children');
2171             $this->fail('Invalid permissions');
2172         } catch (required_capability_exception $e) {
2173             // All good.
2174         }
2176         // User with category permissions.
2177         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2178         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2179         accesslib_clear_all_caches_for_unit_testing();
2180         $result = external::count_templates(array('contextid' => $syscontextid), 'children');
2181         $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2182         $this->assertEquals(3, $result);
2184         // User with system permissions.
2185         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2186         accesslib_clear_all_caches_for_unit_testing();
2187         $result = external::count_templates(array('contextid' => $catcontextid), 'parents');
2188         $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2189         $this->assertEquals(5, $result);
2190     }
2192     /**
2193      * Test that we can add related competencies.
2194      *
2195      * @return void
2196      */
2197     public function test_add_related_competency() {
2198         global $DB;
2199         $this->setUser($this->creator);
2201         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2202         $framework = $lpg->create_framework();
2203         $framework2 = $lpg->create_framework();
2204         $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2205         $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2206         $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2207         $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework2->get_id()));
2209         // The lower one always as competencyid.
2210         $result = external::add_related_competency($competency1->get_id(), $competency2->get_id());
2211         $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2212         $this->assertTrue($result);
2213         $this->assertTrue($DB->record_exists_select(
2214             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2215             array(
2216                 'cid' => $competency1->get_id(),
2217                 'rid' => $competency2->get_id()
2218             )
2219         ));
2220         $this->assertFalse($DB->record_exists_select(
2221             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2222             array(
2223                 'cid' => $competency2->get_id(),
2224                 'rid' => $competency1->get_id()
2225             )
2226         ));
2228         $result = external::add_related_competency($competency3->get_id(), $competency1->get_id());
2229         $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2230         $this->assertTrue($result);
2231         $this->assertTrue($DB->record_exists_select(
2232             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2233             array(
2234                 'cid' => $competency1->get_id(),
2235                 'rid' => $competency3->get_id()
2236             )
2237         ));
2238         $this->assertFalse($DB->record_exists_select(
2239             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2240             array(
2241                 'cid' => $competency3->get_id(),
2242                 'rid' => $competency1->get_id()
2243             )
2244         ));
2246         // We can not allow a duplicate relation, not even in the other direction.
2247         $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2248             'competencyid = :cid AND relatedcompetencyid = :rid',
2249             array('cid' => $competency1->get_id(), 'rid' => $competency2->get_id())));
2250         $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2251             'competencyid = :cid AND relatedcompetencyid = :rid',
2252             array('rid' => $competency1->get_id(), 'cid' => $competency2->get_id())));
2253         $result = external::add_related_competency($competency2->get_id(), $competency1->get_id());
2254         $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2255         $this->assertTrue($result);
2256         $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2257             'competencyid = :cid AND relatedcompetencyid = :rid',
2258             array('cid' => $competency1->get_id(), 'rid' => $competency2->get_id())));
2259         $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2260             'competencyid = :cid AND relatedcompetencyid = :rid',
2261             array('rid' => $competency1->get_id(), 'cid' => $competency2->get_id())));
2263         // Check that we cannot create links across frameworks.
2264         try {
2265             external::add_related_competency($competency1->get_id(), $competency4->get_id());
2266             $this->fail('Exception expected due mis-use of shared competencies');
2267         } catch (invalid_persistent_exception $e) {
2268             // Yay!
2269         }
2271         // User without permission.
2272         $this->setUser($this->user);
2274         // Check we can not add the related competency now.
2275         try {
2276             external::add_related_competency($competency1->get_id(), $competency3->get_id());
2277             $this->fail('Exception expected due to not permissions to manage template competencies');
2278         } catch (moodle_exception $e) {
2279             $this->assertEquals('nopermissions', $e->errorcode);
2280         }
2282     }
2284     /**
2285      * Test that we can remove related competencies.
2286      *
2287      * @return void
2288      */
2289     public function test_remove_related_competency() {
2290         $this->setUser($this->creator);
2292         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2293         $framework = $lpg->create_framework();
2294         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2295         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2296         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2297         $rc1 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c2->get_id()));
2298         $rc2 = $lpg->create_related_competency(array('competencyid' => $c2->get_id(), 'relatedcompetencyid' => $c3->get_id()));
2300         $this->assertEquals(2, related_competency::count_records());
2302         // Returns false when the relation does not exist.
2303         $result = external::remove_related_competency($c1->get_id(), $c3->get_id());
2304         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2305         $this->assertFalse($result);
2307         // Returns true on success.
2308         $result = external::remove_related_competency($c2->get_id(), $c3->get_id());
2309         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2310         $this->assertTrue($result);
2311         $this->assertEquals(1, related_competency::count_records());
2313         // We don't need to specify competencyid and relatedcompetencyid in the right order.
2314         $result = external::remove_related_competency($c2->get_id(), $c1->get_id());
2315         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2316         $this->assertTrue($result);
2317         $this->assertEquals(0, related_competency::count_records());
2318     }
2320     /**
2321      * Test that we can search and include related competencies.
2322      *
2323      * @return void
2324      */
2325     public function test_search_competencies_including_related() {
2326         $this->setUser($this->creator);
2328         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2329         $framework = $lpg->create_framework();
2330         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2331         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2332         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2333         $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2334         $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2336         // We have 1-2, 1-3, 2-4, and no relation between 2-3 nor 1-4 nor 5.
2337         $rc12 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c2->get_id()));
2338         $rc13 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c3->get_id()));
2339         $rc24 = $lpg->create_related_competency(array('competencyid' => $c2->get_id(), 'relatedcompetencyid' => $c4->get_id()));
2341         $result = external::search_competencies('comp', $framework->get_id(), true);
2342         $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
2344         $this->assertCount(5, $result);
2346     }
2348     /**
2349      * Test that we can add competency to plan if we have the right capability.
2350      *
2351      * @return void
2352      */
2353     public function test_add_competency_to_plan() {
2354         $this->resetAfterTest(true);
2355         $dg = $this->getDataGenerator();
2356         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2357         $usermanage = $dg->create_user();
2358         $user = $dg->create_user();
2360         $syscontext = context_system::instance();
2362         // Creating specific roles.
2363         $managerole = $dg->create_role(array(
2364             'name' => 'User manage',
2365             'shortname' => 'manage'
2366         ));
2368         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2369         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2371         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2373         $this->setUser($usermanage);
2374         $plan = array (
2375             'userid' => $usermanage->id,
2376             'status' => \core_competency\plan::STATUS_ACTIVE
2377         );
2378         $pl1 = $lpg->create_plan($plan);
2379         $framework = $lpg->create_framework();
2380         $competency = $lpg->create_competency(
2381                 array('competencyframeworkid' => $framework->get_id())
2382                 );
2383         $this->assertTrue(external::add_competency_to_plan($pl1->get_id(), $competency->get_id()));
2385         // A competency cannot be added to plan based on template.
2386         $template = $lpg->create_template();
2387         $plan = array (
2388             'userid' => $usermanage->id,
2389             'status' => \core_competency\plan::STATUS_ACTIVE,
2390             'templateid' => $template->get_id()
2391         );
2392         $pl2 = $lpg->create_plan($plan);
2393         try {
2394             external::add_competency_to_plan($pl2->get_id(), $competency->get_id());
2395             $this->fail('A competency cannot be added to plan based on template');
2396         } catch (coding_exception $ex) {
2397             $this->assertTrue(true);
2398         }
2400         // User without capability cannot add competency to a plan.
2401         $this->setUser($user);
2402         try {
2403             external::add_competency_to_plan($pl1->get_id(), $competency->get_id());
2404             $this->fail('User without capability cannot add competency to a plan');
2405         } catch (required_capability_exception $ex) {
2406             $this->assertTrue(true);
2407         }
2408     }
2410     /**
2411      * Test that we can add competency to plan if we have the right capability.
2412      *
2413      * @return void
2414      */
2415     public function test_remove_competency_from_plan() {
2416         $this->resetAfterTest(true);
2417         $dg = $this->getDataGenerator();
2418         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2419         $usermanage = $dg->create_user();
2420         $user = $dg->create_user();
2422         $syscontext = context_system::instance();
2424         // Creating specific roles.
2425         $managerole = $dg->create_role(array(
2426             'name' => 'User manage',
2427             'shortname' => 'manage'
2428         ));
2430         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2431         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2433         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2435         $this->setUser($usermanage);
2436         $plan = array (
2437             'userid' => $usermanage->id,
2438             'status' => \core_competency\plan::STATUS_ACTIVE
2439         );
2440         $pl1 = $lpg->create_plan($plan);
2441         $framework = $lpg->create_framework();
2442         $competency = $lpg->create_competency(
2443                 array('competencyframeworkid' => $framework->get_id())
2444                 );
2445         $lpg->create_plan_competency(
2446                 array(
2447                     'planid' => $pl1->get_id(),
2448                     'competencyid' => $competency->get_id()
2449                     )
2450                 );
2451         $this->assertTrue(external::remove_competency_from_plan($pl1->get_id(), $competency->get_id()));
2452         $this->assertCount(0, $pl1->get_competencies());
2453     }
2455     /**
2456      * Test that we can add competency to plan if we have the right capability.
2457      *
2458      * @return void
2459      */
2460     public function test_reorder_plan_competency() {
2461         $this->resetAfterTest(true);
2462         $dg = $this->getDataGenerator();
2463         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2464         $usermanage = $dg->create_user();
2465         $user = $dg->create_user();
2467         $syscontext = context_system::instance();
2469         // Creating specific roles.
2470         $managerole = $dg->create_role(array(
2471             'name' => 'User manage',
2472             'shortname' => 'manage'
2473         ));
2475         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2476         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2478         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2480         $this->setUser($usermanage);
2481         $plan = array (
2482             'userid' => $usermanage->id,
2483             'status' => \core_competency\plan::STATUS_ACTIVE
2484         );
2485         $pl1 = $lpg->create_plan($plan);
2486         $framework = $lpg->create_framework();
2487         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2488         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2489         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2490         $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2491         $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2493         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c1->get_id(), 'sortorder' => 1));
2494         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c2->get_id(), 'sortorder' => 2));
2495         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c3->get_id(), 'sortorder' => 3));
2496         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c4->get_id(), 'sortorder' => 4));
2497         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c5->get_id(), 'sortorder' => 5));
2499         // Test if removing competency from plan don't create sortorder holes.
2500         external::remove_competency_from_plan($pl1->get_id(), $c4->get_id());
2501         $plancomp5 = plan_competency::get_record(array(
2502             'planid' => $pl1->get_id(),
2503             'competencyid' => $c5->get_id()
2504         ));
2506         $this->assertEquals(3, $plancomp5->get_sortorder());
2508         $this->assertTrue(external::reorder_plan_competency($pl1->get_id(), $c2->get_id(), $c5->get_id()));
2509         $this->assertTrue(external::reorder_plan_competency($pl1->get_id(), $c3->get_id(), $c1->get_id()));
2510         $plancompetencies = plan_competency::get_records(array('planid' => $pl1->get_id()), 'sortorder', 'ASC');
2511         $plcmp1 = $plancompetencies[0];
2512         $plcmp2 = $plancompetencies[1];
2513         $plcmp3 = $plancompetencies[2];
2514         $plcmp4 = $plancompetencies[3];
2516         $this->assertEquals($plcmp1->get_competencyid(), $c3->get_id());
2517         $this->assertEquals($plcmp2->get_competencyid(), $c1->get_id());
2518         $this->assertEquals($plcmp3->get_competencyid(), $c5->get_id());
2519         $this->assertEquals($plcmp4->get_competencyid(), $c2->get_id());
2520     }
2522     /**
2523      * Test resolving sortorder when we creating competency.
2524      */
2525     public function test_fix_sortorder_when_creating_competency() {
2526         $this->resetAfterTest(true);
2527         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2528         $framework = $lpg->create_framework();
2530         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2531         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'sortorder' => 20));
2532         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'sortorder' => 1));
2534         $this->assertEquals(0, $c1->get_sortorder());
2535         $this->assertEquals(1, $c2->get_sortorder());
2536         $this->assertEquals(2, $c3->get_sortorder());
2537     }
2539     /**
2540      * Test resolving sortorder when we delete competency.
2541      */
2542     public function test_fix_sortorder_when_delete_competency() {
2543         $this->resetAfterTest(true);
2544         $this->setUser($this->creator);
2545         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2547         $framework = $lpg->create_framework();
2549         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2550         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2551         $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2552         $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2553         $c2c = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2554         $c2d = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2556         $this->assertEquals(0, $c1->get_sortorder());
2557         $this->assertEquals(1, $c2->get_sortorder());
2558         $this->assertEquals(0, $c2a->get_sortorder());
2559         $this->assertEquals(1, $c2b->get_sortorder());
2560         $this->assertEquals(2, $c2c->get_sortorder());
2561         $this->assertEquals(3, $c2d->get_sortorder());
2563         $result = external::delete_competency($c1->get_id());
2564         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2566         $c2->read();
2567         $c2a->read();
2568         $c2b->read();
2569         $c2c->read();
2570         $c2d->read();
2572         $this->assertEquals(0, $c2->get_sortorder());
2573         $this->assertEquals(0, $c2a->get_sortorder());
2574         $this->assertEquals(1, $c2b->get_sortorder());
2575         $this->assertEquals(2, $c2c->get_sortorder());
2576         $this->assertEquals(3, $c2d->get_sortorder());
2578         $result = external::delete_competency($c2b->get_id());
2579         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2581         $c2->read();
2582         $c2a->read();
2583         $c2c->read();
2584         $c2d->read();
2586         $this->assertEquals(0, $c2->get_sortorder());
2587         $this->assertEquals(0, $c2a->get_sortorder());
2588         $this->assertEquals(1, $c2c->get_sortorder());
2589         $this->assertEquals(2, $c2d->get_sortorder());
2590     }
2592     /**
2593      * Test resolving sortorder when moving a competency.
2594      */
2595     public function test_fix_sortorder_when_moving_competency() {
2596         $this->resetAfterTest(true);
2597         $this->setUser($this->creator);
2598         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2600         $framework = $lpg->create_framework();
2602         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2603         $c1a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c1->get_id()));
2604         $c1b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c1->get_id()));
2605         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2606         $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2607         $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2609         $this->assertEquals(0, $c1->get_sortorder());
2610         $this->assertEquals(0, $c1a->get_sortorder());
2611         $this->assertEquals(1, $c1b->get_sortorder());
2612         $this->assertEquals(1, $c2->get_sortorder());
2613         $this->assertEquals(0, $c2a->get_sortorder());
2614         $this->assertEquals(1, $c2b->get_sortorder());
2616         $result = external::set_parent_competency($c2a->get_id(), $c1->get_id());
2617         $result = external_api::clean_returnvalue(external::set_parent_competency_returns(), $result);
2619         $c1->read();
2620         $c1a->read();
2621         $c1b->read();
2622         $c2->read();
2623         $c2a->read();
2624         $c2b->read();
2626         $this->assertEquals(0, $c1->get_sortorder());
2627         $this->assertEquals(0, $c1a->get_sortorder());
2628         $this->assertEquals(1, $c1b->get_sortorder());
2629         $this->assertEquals(2, $c2a->get_sortorder());
2630         $this->assertEquals(1, $c2->get_sortorder());
2631         $this->assertEquals(0, $c2b->get_sortorder());
2633         // Move a root node.
2634         $result = external::set_parent_competency($c2->get_id(), $c1b->get_id());
2635         $result = external_api::clean_returnvalue(external::set_parent_competency_returns(), $result);
2637         $c1->read();
2638         $c1a->read();
2639         $c1b->read();
2640         $c2->read();
2641         $c2a->read();
2642         $c2b->read();
2644         $this->assertEquals(0, $c1->get_sortorder());
2645         $this->assertEquals(0, $c1a->get_sortorder());
2646         $this->assertEquals(1, $c1b->get_sortorder());
2647         $this->assertEquals(0, $c2->get_sortorder());
2648         $this->assertEquals(0, $c2b->get_sortorder());
2649         $this->assertEquals(2, $c2a->get_sortorder());
2650     }
2652     public function test_grade_competency_in_plan() {
2653         global $CFG;
2655         $this->setUser($this->creator);
2657         $dg = $this->getDataGenerator();
2658         $lpg = $dg->get_plugin_generator('core_competency');
2660         $f1 = $lpg->create_framework();
2662         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2664         $tpl = $lpg->create_template();
2665         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id()));
2667         $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id(), 'name' => 'Evil'));
2669         $uc = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1->get_id()));
2671         $evidence = external::grade_competency_in_plan($plan->get_id(), $c1->get_id(), 1, 'Evil note');
2673         $this->assertEquals('The competency rating was manually set in the learning plan \'Evil\'.', $evidence->description);
2674         $this->assertEquals('A', $evidence->gradename);
2675         $this->assertEquals('Evil note', $evidence->note);
2677         $this->setUser($this->user);
2679         $this->setExpectedException('required_capability_exception');
2680         $evidence = external::grade_competency_in_plan($plan->get_id(), $c1->get_id(), 1);
2681     }
2683     /**
2684      * Test update course competency settings.
2685      */
2686     public function test_update_course_competency_settings() {
2687         $this->resetAfterTest(true);
2689         $dg = $this->getDataGenerator();
2691         $course = $dg->create_course();
2692         $roleid = $dg->create_role();
2693         $noobroleid = $dg->create_role();
2694         $context = context_course::instance($course->id);
2695         $compmanager = $this->getDataGenerator()->create_user();
2696         $compnoob = $this->getDataGenerator()->create_user();
2698         assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $roleid, $context->id, true);
2699         assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $roleid, $context->id, true);
2700         assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $noobroleid, $context->id, true);
2702         role_assign($roleid, $compmanager->id, $context->id);
2703         role_assign($noobroleid, $compnoob->id, $context->id);
2704         $dg->enrol_user($compmanager->id, $course->id, $roleid);
2705         $dg->enrol_user($compnoob->id, $course->id, $noobroleid);
2707         $this->setUser($compmanager);
2709         // Start the test.
2710         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2712         $settings = course_competency_settings::get_by_courseid($course->id);
2714         $this->assertTrue((bool)$settings->get_pushratingstouserplans());
2716         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => false));
2718         $settings = course_competency_settings::get_by_courseid($course->id);
2720         $this->assertFalse((bool)$settings->get_pushratingstouserplans());
2721         $this->setUser($compnoob);
2723         $this->setExpectedException('required_capability_exception');
2724         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2725     }