Merge branch 'MDL-50704-master' of git://github.com/FMCorz/moodle
[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 stdClass $scale1 Scale */
73     protected $scale1 = null;
75     /** @var stdClass $scale2 Scale */
76     protected $scale2 = null;
78     /** @var stdClass $scale3 Scale */
79     protected $scale3 = null;
81     /** @var stdClass $scale4 Scale */
82     protected $scale4 = null;
84     /** @var string scaleconfiguration */
85     protected $scaleconfiguration1 = null;
87     /** @var string scaleconfiguration */
88     protected $scaleconfiguration2 = null;
90     /** @var string catscaleconfiguration */
91     protected $scaleconfiguration3 = null;
93     /** @var string catscaleconfiguration */
94     protected $catscaleconfiguration4 = null;
96     /**
97      * Setup function- we will create a course and add an assign instance to it.
98      */
99     protected function setUp() {
100         global $DB;
102         $this->resetAfterTest(true);
104         // Create some users.
105         $creator = $this->getDataGenerator()->create_user();
106         $user = $this->getDataGenerator()->create_user();
107         $catuser = $this->getDataGenerator()->create_user();
108         $category = $this->getDataGenerator()->create_category();
109         $othercategory = $this->getDataGenerator()->create_category();
110         $catcreator = $this->getDataGenerator()->create_user();
112         $syscontext = context_system::instance();
113         $catcontext = context_coursecat::instance($category->id);
114         $othercatcontext = context_coursecat::instance($othercategory->id);
116         // Fetching default authenticated user role.
117         $userroles = get_archetype_roles('user');
118         $this->assertCount(1, $userroles);
119         $authrole = array_pop($userroles);
121         // Reset all default authenticated users permissions.
122         unassign_capability('moodle/competency:competencygrade', $authrole->id);
123         unassign_capability('moodle/competency:competencymanage', $authrole->id);
124         unassign_capability('moodle/competency:competencyview', $authrole->id);
125         unassign_capability('moodle/competency:planmanage', $authrole->id);
126         unassign_capability('moodle/competency:planmanagedraft', $authrole->id);
127         unassign_capability('moodle/competency:planmanageown', $authrole->id);
128         unassign_capability('moodle/competency:planview', $authrole->id);
129         unassign_capability('moodle/competency:planviewdraft', $authrole->id);
130         unassign_capability('moodle/competency:planviewown', $authrole->id);
131         unassign_capability('moodle/competency:planviewowndraft', $authrole->id);
132         unassign_capability('moodle/competency:templatemanage', $authrole->id);
133         unassign_capability('moodle/competency:templateview', $authrole->id);
134         unassign_capability('moodle/cohort:manage', $authrole->id);
135         unassign_capability('moodle/competency:coursecompetencyconfigure', $authrole->id);
137         // Creating specific roles.
138         $this->creatorrole = create_role('Creator role', 'creatorrole', 'learning plan creator role description');
139         $this->userrole = create_role('User role', 'userrole', 'learning plan user role description');
141         assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
142         assign_capability('moodle/competency:competencycompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
143         assign_capability('moodle/competency:competencyview', CAP_ALLOW, $this->userrole, $syscontext->id);
144         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
145         assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
146         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
147         assign_capability('moodle/competency:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id);
148         assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
149         assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
150         assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $this->creatorrole, $syscontext->id);
151         assign_capability('moodle/cohort:manage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
152         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontext->id);
153         assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id);
154         assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
156         role_assign($this->creatorrole, $creator->id, $syscontext->id);
157         role_assign($this->creatorrole, $catcreator->id, $catcontext->id);
158         role_assign($this->userrole, $user->id, $syscontext->id);
159         role_assign($this->userrole, $catuser->id, $catcontext->id);
161         $this->creator = $creator;
162         $this->catcreator = $catcreator;
163         $this->user = $user;
164         $this->catuser = $catuser;
165         $this->category = $category;
166         $this->othercategory = $othercategory;
168         $this->scale1 = $this->getDataGenerator()->create_scale(array("scale" => "value1, value2"));
169         $this->scale2 = $this->getDataGenerator()->create_scale(array("scale" => "value3, value4"));
170         $this->scale3 = $this->getDataGenerator()->create_scale(array("scale" => "value5, value6"));
171         $this->scale4 = $this->getDataGenerator()->create_scale(array("scale" => "value7, value8"));
173         $this->scaleconfiguration1 = '[{"scaleid":"'.$this->scale1->id.'"},' .
174                 '{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
175                 '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
176         $this->scaleconfiguration2 = '[{"scaleid":"'.$this->scale2->id.'"},' .
177                 '{"name":"value3","id":1,"scaledefault":1,"proficient":0},' .
178                 '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
179         $this->scaleconfiguration3 = '[{"scaleid":"'.$this->scale3->id.'"},' .
180                 '{"name":"value5","id":1,"scaledefault":1,"proficient":0},' .
181                 '{"name":"value6","id":2,"scaledefault":0,"proficient":1}]';
182         $this->scaleconfiguration4 = '[{"scaleid":"'.$this->scale4->id.'"},'.
183                 '{"name":"value8","id":1,"scaledefault":1,"proficient":0},' .
184                 '{"name":"value8","id":2,"scaledefault":0,"proficient":1}]';
185         accesslib_clear_all_caches_for_unit_testing();
186     }
189     protected function create_competency_framework($number = 1, $system = true) {
190         $scalename = 'scale' . $number;
191         $scalepropname = 'scaleconfiguration' . $number;
192         $framework = array(
193             'shortname' => 'shortname' . $number,
194             'idnumber' => 'idnumber' . $number,
195             'description' => 'description' . $number,
196             'descriptionformat' => FORMAT_HTML,
197             'scaleid' => $this->$scalename->id,
198             'scaleconfiguration' => $this->$scalepropname,
199             'visible' => true,
200             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
201         );
202         $result = external::create_competency_framework($framework);
203         return (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result);
204     }
206     protected function create_plan($number, $userid, $templateid, $status, $duedate) {
207         $plan = array(
208             'name' => 'name' . $number,
209             'description' => 'description' . $number,
210             'descriptionformat' => FORMAT_HTML,
211             'userid' => $userid,
212             'templateid' => empty($templateid) ? null : $templateid,
213             'status' => $status,
214             'duedate' => $duedate
215         );
216         $result = external::create_plan($plan);
217         return (object) external_api::clean_returnvalue(external::create_plan_returns(), $result);
218     }
220     protected function create_template($number, $system) {
221         $template = array(
222             'shortname' => 'shortname' . $number,
223             'description' => 'description' . $number,
224             'descriptionformat' => FORMAT_HTML,
225             'duedate' => 0,
226             'visible' => true,
227             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
228         );
229         $result = external::create_template($template);
230         return (object) external_api::clean_returnvalue(external::create_template_returns(), $result);
231     }
233     protected function update_template($templateid, $number) {
234         $template = array(
235             'id' => $templateid,
236             'shortname' => 'shortname' . $number,
237             'description' => 'description' . $number,
238             'descriptionformat' => FORMAT_HTML,
239             'visible' => true
240         );
241         $result = external::update_template($template);
242         return external_api::clean_returnvalue(external::update_template_returns(), $result);
243     }
245     protected function update_plan($planid, $number, $userid, $templateid, $status, $duedate) {
246         $plan = array(
247             'id' => $planid,
248             'name' => 'name' . $number,
249             'description' => 'description' . $number,
250             'descriptionformat' => FORMAT_HTML,
251             'userid' => $userid,
252             'templateid' => $templateid,
253             'status' => $status,
254             'duedate' => $duedate
255         );
256         $result = external::update_plan($plan);
257         return external_api::clean_returnvalue(external::update_plan_returns(), $result);
258     }
260     protected function update_competency_framework($id, $number = 1, $system = true) {
261         $scalename = 'scale' . $number;
262         $scalepropname = 'scaleconfiguration' . $number;
263         $framework = array(
264             'id' => $id,
265             'shortname' => 'shortname' . $number,
266             'idnumber' => 'idnumber' . $number,
267             'description' => 'description' . $number,
268             'descriptionformat' => FORMAT_HTML,
269             'scaleid' => $this->$scalename->id,
270             'scaleconfiguration' => $this->$scalepropname,
271             'visible' => true,
272             'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
273         );
274         $result = external::update_competency_framework($framework);
275         return external_api::clean_returnvalue(external::update_competency_framework_returns(), $result);
276     }
278     protected function create_competency($number, $frameworkid) {
279         $competency = array(
280             'shortname' => 'shortname' . $number,
281             'idnumber' => 'idnumber' . $number,
282             'description' => 'description' . $number,
283             'descriptionformat' => FORMAT_HTML,
284             'competencyframeworkid' => $frameworkid,
285             'sortorder' => 0
286         );
287         $result = external::create_competency($competency);
288         return (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
289     }
291     protected function update_competency($id, $number) {
292         $competency = array(
293             'id' => $id,
294             'shortname' => 'shortname' . $number,
295             'idnumber' => 'idnumber' . $number,
296             'description' => 'description' . $number,
297             'descriptionformat' => FORMAT_HTML,
298             'sortorder' => 0
299         );
300         $result = external::update_competency($competency);
301         return external_api::clean_returnvalue(external::update_competency_returns(), $result);
302     }
304     /**
305      * Test we can't create a competency framework with only read permissions.
306      */
307     public function test_create_competency_frameworks_with_read_permissions() {
308         $this->setExpectedException('required_capability_exception');
309         $this->setUser($this->user);
311         $result = $this->create_competency_framework(1, true);
312     }
314     /**
315      * Test we can't create a competency framework with only read permissions.
316      */
317     public function test_create_competency_frameworks_with_read_permissions_in_category() {
318         $this->setExpectedException('required_capability_exception');
319         $this->setUser($this->catuser);
320         $result = $this->create_competency_framework(1, false);
321     }
323     /**
324      * Test we can create a competency framework with manage permissions.
325      */
326     public function test_create_competency_frameworks_with_manage_permissions() {
327         $this->setUser($this->creator);
328         $result = $this->create_competency_framework(1, true);
330         $this->assertGreaterThan(0, $result->timecreated);
331         $this->assertGreaterThan(0, $result->timemodified);
332         $this->assertEquals($this->creator->id, $result->usermodified);
333         $this->assertEquals('shortname1', $result->shortname);
334         $this->assertEquals('idnumber1', $result->idnumber);
335         $this->assertEquals('description1', $result->description);
336         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
337         $this->assertEquals($this->scale1->id, $result->scaleid);
338         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
339         $this->assertEquals(true, $result->visible);
340     }
342     /**
343      * Test we can create a competency framework with manage permissions.
344      */
345     public function test_create_competency_frameworks_with_manage_permissions_in_category() {
346         $this->setUser($this->catcreator);
347         $result = $this->create_competency_framework(1, false);
349         $this->assertGreaterThan(0, $result->timecreated);
350         $this->assertGreaterThan(0, $result->timemodified);
351         $this->assertEquals($this->catcreator->id, $result->usermodified);
352         $this->assertEquals('shortname1', $result->shortname);
353         $this->assertEquals('idnumber1', $result->idnumber);
354         $this->assertEquals('description1', $result->description);
355         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
356         $this->assertEquals($this->scale1->id, $result->scaleid);
357         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
358         $this->assertEquals(true, $result->visible);
360         try {
361             $result = $this->create_competency_framework(1, true);
362             $this->fail('User cannot create a framework at system level.');
363         } catch (required_capability_exception $e) {
364             // All good.
365         }
366     }
368     /**
369      * Test we cannot create a competency framework with nasty data.
370      */
371     public function test_create_competency_frameworks_with_nasty_data() {
372         $this->setUser($this->creator);
373         $this->setExpectedException('invalid_parameter_exception');
374         $framework = array(
375             'shortname' => 'short<a href="">',
376             'idnumber' => 'id;"number',
377             'description' => 'de<>\\..scription',
378             'descriptionformat' => FORMAT_HTML,
379             'scaleid' => $this->scale1->id,
380             'scaleconfiguration' => $this->scaleconfiguration1,
381             'visible' => true,
382             'contextid' => context_system::instance()->id
383         );
384         $result = external::create_competency_framework($framework);
385     }
387     /**
388      * Test we can read a competency framework with manage permissions.
389      */
390     public function test_read_competency_frameworks_with_manage_permissions() {
391         $this->setUser($this->creator);
392         $result = $this->create_competency_framework(1, true);
394         $id = $result->id;
395         $result = external::read_competency_framework($id);
396         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
398         $this->assertGreaterThan(0, $result->timecreated);
399         $this->assertGreaterThan(0, $result->timemodified);
400         $this->assertEquals($this->creator->id, $result->usermodified);
401         $this->assertEquals('shortname1', $result->shortname);
402         $this->assertEquals('idnumber1', $result->idnumber);
403         $this->assertEquals('description1', $result->description);
404         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
405         $this->assertEquals($this->scale1->id, $result->scaleid);
406         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
407         $this->assertEquals(true, $result->visible);
408     }
410     /**
411      * Test we can read a competency framework with manage permissions.
412      */
413     public function test_read_competency_frameworks_with_manage_permissions_in_category() {
414         $this->setUser($this->creator);
416         $insystem = $this->create_competency_framework(1, true);
417         $incat = $this->create_competency_framework(2, false);
419         $this->setUser($this->catcreator);
420         $id = $incat->id;
421         $result = external::read_competency_framework($id);
422         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
424         $this->assertGreaterThan(0, $result->timecreated);
425         $this->assertGreaterThan(0, $result->timemodified);
426         $this->assertEquals($this->creator->id, $result->usermodified);
427         $this->assertEquals('shortname2', $result->shortname);
428         $this->assertEquals('idnumber2', $result->idnumber);
429         $this->assertEquals('description2', $result->description);
430         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
431         $this->assertEquals($this->scale2->id, $result->scaleid);
432         $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
433         $this->assertEquals(true, $result->visible);
435         try {
436             $id = $insystem->id;
437             $result = external::read_competency_framework($id);
438             $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
439             $this->fail('User cannot read a framework at system level.');
440         } catch (required_capability_exception $e) {
441             // All good.
442         }
443     }
445     /**
446      * Test we can read a competency framework with read permissions.
447      */
448     public function test_read_competency_frameworks_with_read_permissions() {
449         $this->setUser($this->creator);
450         $result = $this->create_competency_framework(1, true);
452         // Switch users to someone with less permissions.
453         $this->setUser($this->user);
454         $id = $result->id;
455         $result = external::read_competency_framework($id);
456         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
458         $this->assertGreaterThan(0, $result->timecreated);
459         $this->assertGreaterThan(0, $result->timemodified);
460         $this->assertEquals($this->creator->id, $result->usermodified);
461         $this->assertEquals('shortname1', $result->shortname);
462         $this->assertEquals('idnumber1', $result->idnumber);
463         $this->assertEquals('description1', $result->description);
464         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
465         $this->assertEquals($this->scale1->id, $result->scaleid);
466         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
467         $this->assertEquals(true, $result->visible);
468     }
469     /**
470      * Test we can read a competency framework with read permissions.
471      */
472     public function test_read_competency_frameworks_with_read_permissions_in_category() {
473         $this->setUser($this->creator);
475         $insystem = $this->create_competency_framework(1, true);
476         $incat = $this->create_competency_framework(2, false);
478         // Switch users to someone with less permissions.
479         $this->setUser($this->catuser);
480         $id = $incat->id;
481         $result = external::read_competency_framework($id);
482         $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
484         $this->assertGreaterThan(0, $result->timecreated);
485         $this->assertGreaterThan(0, $result->timemodified);
486         $this->assertEquals($this->creator->id, $result->usermodified);
487         $this->assertEquals('shortname2', $result->shortname);
488         $this->assertEquals('idnumber2', $result->idnumber);
489         $this->assertEquals('description2', $result->description);
490         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
491         $this->assertEquals($this->scale2->id, $result->scaleid);
492         $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
493         $this->assertEquals(true, $result->visible);
495         // Switching to user with no permissions.
496         try {
497             $result = external::read_competency_framework($insystem->id);
498             $this->fail('Current user cannot should not be able to read the framework.');
499         } catch (required_capability_exception $e) {
500             // All good.
501         }
502     }
504     /**
505      * Test we can delete a competency framework with manage permissions.
506      */
507     public function test_delete_competency_frameworks_with_manage_permissions() {
508         $this->setUser($this->creator);
509         $result = $this->create_competency_framework(1, true);
511         $id = $result->id;
512         $result = external::delete_competency_framework($id);
513         $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
515         $this->assertTrue($result);
516     }
518     /**
519      * Test we can delete a competency framework with manage permissions.
520      */
521     public function test_delete_competency_frameworks_with_manage_permissions_in_category() {
522         $this->setUser($this->creator);
524         $insystem = $this->create_competency_framework(1, true);
525         $incat = $this->create_competency_framework(2, false);
527         $this->setUser($this->catcreator);
528         $id = $incat->id;
529         $result = external::delete_competency_framework($id);
530         $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
532         $this->assertTrue($result);
534         try {
535             $id = $insystem->id;
536             $result = external::delete_competency_framework($id);
537             $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
538             $this->fail('Current user cannot should not be able to delete the framework.');
539         } catch (required_capability_exception $e) {
540             // All good.
541         }
542     }
544     /**
545      * Test we can delete a competency framework with read permissions.
546      */
547     public function test_delete_competency_frameworks_with_read_permissions() {
548         $this->setExpectedException('required_capability_exception');
549         $this->setUser($this->creator);
550         $result = $this->create_competency_framework(1, true);
552         $id = $result->id;
553         // Switch users to someone with less permissions.
554         $this->setUser($this->user);
555         $result = external::delete_competency_framework($id);
556     }
558     /**
559      * Test we can update a competency framework with manage permissions.
560      */
561     public function test_update_competency_frameworks_with_manage_permissions() {
562         $this->setUser($this->creator);
563         $result = $this->create_competency_framework(1, true);
565         $result = $this->update_competency_framework($result->id, 2, true);
567         $this->assertTrue($result);
568     }
570     /**
571      * Test we can update a competency framework with manage permissions.
572      */
573     public function test_update_competency_frameworks_with_manage_permissions_in_category() {
574         $this->setUser($this->creator);
576         $insystem = $this->create_competency_framework(1, true);
577         $incat = $this->create_competency_framework(2, false);
579         $this->setUser($this->catcreator);
580         $id = $incat->id;
582         $result = $this->update_competency_framework($incat->id, 3, false);
584         $this->assertTrue($result);
586         try {
587             $result = $this->update_competency_framework($insystem->id, 4, true);
588             $this->fail('Current user should not be able to update the framework.');
589         } catch (required_capability_exception $e) {
590             // All good.
591         }
592     }
594     public function test_update_framework_scale() {
595         $this->setUser($this->creator);
596         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
598         $s1 = $this->getDataGenerator()->create_scale();
600         $f1 = $lpg->create_framework(array('scaleid' => $s1->id));
601         $f2 = $lpg->create_framework(array('scaleid' => $s1->id));
602         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
603         $c2 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
605         $this->assertEquals($s1->id, $f1->get_scaleid());
607         // Make the scale of f2 being used.
608         $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2->get_id()));
610         // Changing the framework where the scale is not used.
611         $result = $this->update_competency_framework($f1->get_id(), 3, true);
613         $f1 = new \core_competency\competency_framework($f1->get_id());
614         $this->assertEquals($this->scale3->id, $f1->get_scaleid());
616         // Changing the framework where the scale is used.
617         try {
618             $result = $this->update_competency_framework($f2->get_id(), 4, true);
619             $this->fail('The scale cannot be changed once used.');
620         } catch (\core_competency\invalid_persistent_exception $e) {
621             $this->assertRegexp('/scaleid/', $e->getMessage());
622         }
623     }
625     /**
626      * Test we can update a competency framework with read permissions.
627      */
628     public function test_update_competency_frameworks_with_read_permissions() {
629         $this->setExpectedException('required_capability_exception');
630         $this->setUser($this->creator);
631         $result = $this->create_competency_framework(1, true);
633         $this->setUser($this->user);
634         $result = $this->update_competency_framework($result->id, 2, true);
635     }
637     /**
638      * Test we can list and count competency frameworks with manage permissions.
639      */
640     public function test_list_and_count_competency_frameworks_with_manage_permissions() {
641         $this->setUser($this->creator);
642         $result = $this->create_competency_framework(1, true);
643         $result = $this->create_competency_framework(2, true);
644         $result = $this->create_competency_framework(3, true);
645         $result = $this->create_competency_framework(4, false);
647         $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
648         $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
650         $this->assertEquals($result, 3);
652         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
653             array('contextid' => context_system::instance()->id), 'self', false);
654         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
656         $this->assertEquals(count($result), 3);
657         $result = (object) $result[0];
659         $this->assertGreaterThan(0, $result->timecreated);
660         $this->assertGreaterThan(0, $result->timemodified);
661         $this->assertEquals($this->creator->id, $result->usermodified);
662         $this->assertEquals('shortname1', $result->shortname);
663         $this->assertEquals('idnumber1', $result->idnumber);
664         $this->assertEquals('description1', $result->description);
665         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
666         $this->assertEquals($this->scale1->id, $result->scaleid);
667         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
668         $this->assertEquals(true, $result->visible);
669     }
671     public function test_list_competency_frameworks_with_query() {
672         $this->setUser($this->creator);
673         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
674         $framework1 = $lpg->create_framework(array(
675             'shortname' => 'shortname_beetroot',
676             'idnumber' => 'idnumber_cinnamon',
677             'description' => 'description',
678             'descriptionformat' => FORMAT_HTML,
679             'visible' => true,
680             'contextid' => context_system::instance()->id
681         ));
682         $framework2 = $lpg->create_framework(array(
683             'shortname' => 'shortname_citrus',
684             'idnumber' => 'idnumber_beer',
685             'description' => 'description',
686             'descriptionformat' => FORMAT_HTML,
687             'visible' => true,
688             'contextid' => context_system::instance()->id
689         ));
691         // Search on both ID number and shortname.
692         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
693             array('contextid' => context_system::instance()->id), 'self', false, 'bee');
694         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
695         $this->assertCount(2, $result);
696         $f = (object) array_shift($result);
697         $this->assertEquals($framework1->get_id(), $f->id);
698         $f = (object) array_shift($result);
699         $this->assertEquals($framework2->get_id(), $f->id);
701         // Search on ID number.
702         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
703             array('contextid' => context_system::instance()->id), 'self', false, 'beer');
704         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
705         $this->assertCount(1, $result);
706         $f = (object) array_shift($result);
707         $this->assertEquals($framework2->get_id(), $f->id);
709         // Search on shortname.
710         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
711             array('contextid' => context_system::instance()->id), 'self', false, 'cinnamon');
712         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
713         $this->assertCount(1, $result);
714         $f = (object) array_shift($result);
715         $this->assertEquals($framework1->get_id(), $f->id);
717         // No match.
718         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
719             array('contextid' => context_system::instance()->id), 'self', false, 'pwnd!');
720         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
721         $this->assertCount(0, $result);
722     }
724     /**
725      * Test we can list and count competency frameworks with read permissions.
726      */
727     public function test_list_and_count_competency_frameworks_with_read_permissions() {
728         $this->setUser($this->creator);
729         $result = $this->create_competency_framework(1, true);
730         $result = $this->create_competency_framework(2, true);
731         $result = $this->create_competency_framework(3, true);
732         $result = $this->create_competency_framework(4, false);
734         $this->setUser($this->user);
735         $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
736         $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
737         $this->assertEquals($result, 3);
739         $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
740             array('contextid' => context_system::instance()->id), 'self', false);
741         $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
743         $this->assertEquals(count($result), 3);
744         $result = (object) $result[0];
746         $this->assertGreaterThan(0, $result->timecreated);
747         $this->assertGreaterThan(0, $result->timemodified);
748         $this->assertEquals($this->creator->id, $result->usermodified);
749         $this->assertEquals('shortname1', $result->shortname);
750         $this->assertEquals('idnumber1', $result->idnumber);
751         $this->assertEquals('description1', $result->description);
752         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
753         $this->assertEquals($this->scale1->id, $result->scaleid);
754         $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
755         $this->assertEquals(true, $result->visible);
756     }
758     /**
759      * Test we can't create a competency with only read permissions.
760      */
761     public function test_create_competency_with_read_permissions() {
762         $this->setExpectedException('required_capability_exception');
763         $framework = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_framework();
764         $this->setUser($this->user);
765         $competency = $this->create_competency(1, $framework->get_id());
766     }
768     /**
769      * Test we can create a competency with manage permissions.
770      */
771     public function test_create_competency_with_manage_permissions() {
772         $this->setUser($this->creator);
773         $framework = $this->create_competency_framework(1, true);
774         $competency = $this->create_competency(1, $framework->id);
776         $this->assertGreaterThan(0, $competency->timecreated);
777         $this->assertGreaterThan(0, $competency->timemodified);
778         $this->assertEquals($this->creator->id, $competency->usermodified);
779         $this->assertEquals('shortname1', $competency->shortname);
780         $this->assertEquals('idnumber1', $competency->idnumber);
781         $this->assertEquals('description1', $competency->description);
782         $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
783         $this->assertEquals(0, $competency->parentid);
784         $this->assertEquals($framework->id, $competency->competencyframeworkid);
785     }
788     /**
789      * Test we can create a competency with manage permissions.
790      */
791     public function test_create_competency_with_manage_permissions_in_category() {
792         $this->setUser($this->creator);
794         $insystem = $this->create_competency_framework(1, true);
795         $incat = $this->create_competency_framework(2, false);
797         $this->setUser($this->catcreator);
799         $competency = $this->create_competency(1, $incat->id);
801         $this->assertGreaterThan(0, $competency->timecreated);
802         $this->assertGreaterThan(0, $competency->timemodified);
803         $this->assertEquals($this->catcreator->id, $competency->usermodified);
804         $this->assertEquals('shortname1', $competency->shortname);
805         $this->assertEquals('idnumber1', $competency->idnumber);
806         $this->assertEquals('description1', $competency->description);
807         $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
808         $this->assertEquals(0, $competency->parentid);
809         $this->assertEquals($incat->id, $competency->competencyframeworkid);
811         try {
812             $competency = $this->create_competency(2, $insystem->id);
813             $this->fail('User should not be able to create a competency in system context.');
814         } catch (required_capability_exception $e) {
815             // All good.
816         }
817     }
819     /**
820      * Test we cannot create a competency with nasty data.
821      */
822     public function test_create_competency_with_nasty_data() {
823         $this->setUser($this->creator);
824         $framework = $this->create_competency_framework(1, true);
825         $this->setExpectedException('invalid_parameter_exception');
826         $competency = array(
827             'shortname' => 'shortname<a href="">',
828             'idnumber' => 'id;"number',
829             'description' => 'de<>\\..scription',
830             'descriptionformat' => FORMAT_HTML,
831             'competencyframeworkid' => $framework->id,
832             'sortorder' => 0
833         );
834         $result = external::create_competency($competency);
835         $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
836     }
838     /**
839      * Test we can read a competency with manage permissions.
840      */
841     public function test_read_competencies_with_manage_permissions() {
842         $this->setUser($this->creator);
843         $framework = $this->create_competency_framework(1, true);
844         $competency = $this->create_competency(1, $framework->id);
846         $id = $competency->id;
847         $result = external::read_competency($id);
848         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
850         $this->assertGreaterThan(0, $result->timecreated);
851         $this->assertGreaterThan(0, $result->timemodified);
852         $this->assertEquals($this->creator->id, $result->usermodified);
853         $this->assertEquals('shortname1', $result->shortname);
854         $this->assertEquals('idnumber1', $result->idnumber);
855         $this->assertEquals('description1', $result->description);
856         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
857         $this->assertEquals(0, $result->parentid);
858         $this->assertEquals($framework->id, $result->competencyframeworkid);
859     }
861     /**
862      * Test we can read a competency with manage permissions.
863      */
864     public function test_read_competencies_with_manage_permissions_in_category() {
865         $this->setUser($this->creator);
867         $sysframework = $this->create_competency_framework(1, true);
868         $insystem = $this->create_competency(1, $sysframework->id);
870         $catframework = $this->create_competency_framework(2, false);
871         $incat = $this->create_competency(2, $catframework->id);
873         $this->setUser($this->catcreator);
874         $id = $incat->id;
875         $result = external::read_competency($id);
876         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
878         $this->assertGreaterThan(0, $result->timecreated);
879         $this->assertGreaterThan(0, $result->timemodified);
880         $this->assertEquals($this->creator->id, $result->usermodified);
881         $this->assertEquals('shortname2', $result->shortname);
882         $this->assertEquals('idnumber2', $result->idnumber);
883         $this->assertEquals('description2', $result->description);
884         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
885         $this->assertEquals(0, $result->parentid);
886         $this->assertEquals($catframework->id, $result->competencyframeworkid);
888         try {
889             external::read_competency($insystem->id);
890             $this->fail('User should not be able to read a competency in system context.');
891         } catch (required_capability_exception $e) {
892             // All good.
893         }
894     }
896     /**
897      * Test we can read a competency with read permissions.
898      */
899     public function test_read_competencies_with_read_permissions() {
900         $this->setUser($this->creator);
901         $framework = $this->create_competency_framework(1, true);
902         $competency = $this->create_competency(1, $framework->id);
904         // Switch users to someone with less permissions.
905         $this->setUser($this->user);
906         $id = $competency->id;
907         $result = external::read_competency($id);
908         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
910         $this->assertGreaterThan(0, $result->timecreated);
911         $this->assertGreaterThan(0, $result->timemodified);
912         $this->assertEquals($this->creator->id, $result->usermodified);
913         $this->assertEquals('shortname1', $result->shortname);
914         $this->assertEquals('idnumber1', $result->idnumber);
915         $this->assertEquals('description1', $result->description);
916         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
917         $this->assertEquals(0, $result->parentid);
918         $this->assertEquals($framework->id, $result->competencyframeworkid);
919     }
921     /**
922      * Test we can read a competency with read permissions.
923      */
924     public function test_read_competencies_with_read_permissions_in_category() {
925         $this->setUser($this->creator);
926         $sysframework = $this->create_competency_framework(1, true);
927         $insystem = $this->create_competency(1, $sysframework->id);
928         $catframework = $this->create_competency_framework(2, false);
929         $incat = $this->create_competency(2, $catframework->id);
931         // Switch users to someone with less permissions.
932         $this->setUser($this->catuser);
933         $id = $incat->id;
934         $result = external::read_competency($id);
935         $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
937         $this->assertGreaterThan(0, $result->timecreated);
938         $this->assertGreaterThan(0, $result->timemodified);
939         $this->assertEquals($this->creator->id, $result->usermodified);
940         $this->assertEquals('shortname2', $result->shortname);
941         $this->assertEquals('idnumber2', $result->idnumber);
942         $this->assertEquals('description2', $result->description);
943         $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
944         $this->assertEquals(0, $result->parentid);
945         $this->assertEquals($catframework->id, $result->competencyframeworkid);
947         try {
948             external::read_competency($insystem->id);
949             $this->fail('User should not be able to read a competency in system context.');
950         } catch (required_capability_exception $e) {
951             // All good.
952         }
953     }
955     /**
956      * Test we can delete a competency with manage permissions.
957      */
958     public function test_delete_competency_with_manage_permissions() {
959         $this->setUser($this->creator);
960         $framework = $this->create_competency_framework(1, true);
961         $result = $this->create_competency(1, $framework->id);
963         $id = $result->id;
964         $result = external::delete_competency($id);
965         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
967         $this->assertTrue($result);
968     }
970     /**
971      * Test we can delete a competency with manage permissions.
972      */
973     public function test_delete_competency_with_manage_permissions_in_category() {
974         $this->setUser($this->creator);
976         $sysframework = $this->create_competency_framework(1, true);
977         $insystem = $this->create_competency(1, $sysframework->id);
978         $catframework = $this->create_competency_framework(2, false);
979         $incat = $this->create_competency(2, $catframework->id);
981         $this->setUser($this->catcreator);
982         $id = $incat->id;
983         $result = external::delete_competency($id);
984         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
986         $this->assertTrue($result);
988         try {
989             $result = external::delete_competency($insystem->id);
990             $this->fail('User should not be able to delete a competency in system context.');
991         } catch (required_capability_exception $e) {
992             // All good.
993         }
994     }
996     /**
997      * Test we can delete a competency with read permissions.
998      */
999     public function test_delete_competency_with_read_permissions() {
1000         $this->setExpectedException('required_capability_exception');
1001         $this->setUser($this->creator);
1002         $framework = $this->create_competency_framework(1, true);
1003         $result = $this->create_competency(1, $framework->id);
1005         $id = $result->id;
1006         // Switch users to someone with less permissions.
1007         $this->setUser($this->user);
1008         $result = external::delete_competency($id);
1009     }
1011     /**
1012      * Test we can update a competency with manage permissions.
1013      */
1014     public function test_update_competency_with_manage_permissions() {
1015         $this->setUser($this->creator);
1016         $framework = $this->create_competency_framework(1, true);
1017         $result = $this->create_competency(1, $framework->id);
1019         $result = $this->update_competency($result->id, 2);
1021         $this->assertTrue($result);
1022     }
1024     /**
1025      * Test we can update a competency with manage permissions.
1026      */
1027     public function test_update_competency_with_manage_permissions_in_category() {
1028         $this->setUser($this->creator);
1030         $sysframework = $this->create_competency_framework(1, true);
1031         $insystem = $this->create_competency(1, $sysframework->id);
1032         $catframework = $this->create_competency_framework(2, false);
1033         $incat = $this->create_competency(2, $catframework->id);
1035         $this->setUser($this->catcreator);
1037         $result = $this->update_competency($incat->id, 2);
1039         $this->assertTrue($result);
1041         try {
1042             $result = $this->update_competency($insystem->id, 3);
1043             $this->fail('User should not be able to update a competency in system context.');
1044         } catch (required_capability_exception $e) {
1045             // All good.
1046         }
1047     }
1049     /**
1050      * Test we can update a competency with read permissions.
1051      */
1052     public function test_update_competency_with_read_permissions() {
1053         $this->setExpectedException('required_capability_exception');
1054         $this->setUser($this->creator);
1055         $framework = $this->create_competency_framework(1, true);
1056         $result = $this->create_competency(1, $framework->id);
1058         $this->setUser($this->user);
1059         $result = $this->update_competency($result->id, 2);
1060     }
1062     /**
1063      * Test count competencies with filters.
1064      */
1065     public function test_count_competencies_with_filters() {
1066         $this->setUser($this->creator);
1068         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1069         $f1 = $lpg->create_framework();
1070         $f2 = $lpg->create_framework();
1071         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1072         $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'shortname' => 'A'));
1073         $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1074         $c4 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1075         $c5 = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1077         $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f2->get_id())));
1078         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1079         $this->assertEquals(2, $result);
1081         $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f1->get_id())));
1082         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1083         $this->assertEquals(3, $result);
1085         $result = external::count_competencies(array(array('column' => 'shortname', 'value' => 'A')));
1086         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1087         $this->assertEquals(1, $result);
1088     }
1090     /**
1091      * Test we can list and count competencies with manage permissions.
1092      */
1093     public function test_list_and_count_competencies_with_manage_permissions() {
1094         $this->setUser($this->creator);
1095         $framework = $this->create_competency_framework(1, true);
1096         $result = $this->create_competency(1, $framework->id);
1097         $result = $this->create_competency(2, $framework->id);
1098         $result = $this->create_competency(3, $framework->id);
1100         $result = external::count_competencies(array());
1101         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1103         $this->assertEquals($result, 3);
1105         array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1106         $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1108         $this->assertEquals(count($result), 3);
1109         $result = (object) $result[0];
1111         $this->assertGreaterThan(0, $result->timecreated);
1112         $this->assertGreaterThan(0, $result->timemodified);
1113         $this->assertEquals($this->creator->id, $result->usermodified);
1114         $this->assertEquals('shortname1', $result->shortname);
1115         $this->assertEquals('idnumber1', $result->idnumber);
1116         $this->assertEquals('description1', $result->description);
1117     }
1119     /**
1120      * Test we can list and count competencies with read permissions.
1121      */
1122     public function test_list_and_count_competencies_with_read_permissions() {
1123         $this->setUser($this->creator);
1124         $framework = $this->create_competency_framework(1, true);
1125         $result = $this->create_competency(1, $framework->id);
1126         $result = $this->create_competency(2, $framework->id);
1127         $result = $this->create_competency(3, $framework->id);
1129         $this->setUser($this->user);
1131         $result = external::count_competencies(array());
1132         $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1134         $this->assertEquals($result, 3);
1136         array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1137         $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1139         $this->assertEquals(count($result), 3);
1140         $result = (object) $result[0];
1142         $this->assertGreaterThan(0, $result->timecreated);
1143         $this->assertGreaterThan(0, $result->timemodified);
1144         $this->assertEquals($this->creator->id, $result->usermodified);
1145         $this->assertEquals('shortname1', $result->shortname);
1146         $this->assertEquals('idnumber1', $result->idnumber);
1147         $this->assertEquals('description1', $result->description);
1148     }
1150     /**
1151      * Test we can search for competencies.
1152      */
1153     public function test_search_competencies_with_read_permissions() {
1154         $this->setUser($this->creator);
1155         $framework = $this->create_competency_framework(1, true);
1156         $result = $this->create_competency(1, $framework->id);
1157         $result = $this->create_competency(2, $framework->id);
1158         $result = $this->create_competency(3, $framework->id);
1160         $this->setUser($this->user);
1162         $result = external::search_competencies('short', $framework->id);
1163         $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
1165         $this->assertEquals(count($result), 3);
1166         $result = (object) $result[0];
1168         $this->assertGreaterThan(0, $result->timecreated);
1169         $this->assertGreaterThan(0, $result->timemodified);
1170         $this->assertEquals($this->creator->id, $result->usermodified);
1171         $this->assertEquals('shortname1', $result->shortname);
1172         $this->assertEquals('idnumber1', $result->idnumber);
1173         $this->assertEquals('description1', $result->description);
1174     }
1176     /**
1177      * Test plans creation and updates.
1178      */
1179     public function test_create_and_update_plans() {
1180         $syscontext = context_system::instance();
1182         $this->setUser($this->creator);
1183         $plan0 = $this->create_plan(1, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1185         $this->setUser($this->user);
1187         try {
1188             $plan1 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1189             $this->fail('Exception expected due to not permissions to create draft plans');
1190         } catch (moodle_exception $e) {
1191             $this->assertEquals('nopermissions', $e->errorcode);
1192         }
1194         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1195         accesslib_clear_all_caches_for_unit_testing();
1197         $this->setUser($this->user);
1199         $plan2 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1201         try {
1202             $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1203             $this->fail('Exception expected due to not permissions to create active plans');
1204         } catch (moodle_exception $e) {
1205             $this->assertEquals('nopermissions', $e->errorcode);
1206         }
1207         try {
1208             $plan3 = $this->update_plan($plan2->id, 4, $this->user->id, 0, plan::STATUS_COMPLETE, 0);
1209             $this->fail('We cannot complete a plan using api::update_plan().');
1210         } catch (coding_exception $e) {
1211             $this->assertTrue(true);
1212         }
1214         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1215         accesslib_clear_all_caches_for_unit_testing();
1217         $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1218         try {
1219             $plan4 = $this->create_plan(6, $this->creator->id, 0, plan::STATUS_COMPLETE, 0);
1220             $this->fail('Plans cannot be created as complete.');
1221         } catch (coding_exception $e) {
1222             $this->assertRegexp('/A plan cannot be created as complete./', $e->getMessage());
1223         }
1225         try {
1226             $plan0 = $this->update_plan($plan0->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1227         } catch (moodle_exception $e) {
1228             $this->assertEquals('nopermissions', $e->errorcode);
1229         }
1231         unassign_capability('moodle/competency:planmanageown', $this->userrole, $syscontext->id);
1232         unassign_capability('moodle/competency:planmanageowndraft', $this->userrole, $syscontext->id);
1233         accesslib_clear_all_caches_for_unit_testing();
1235         try {
1236             // Cannot be updated even if they created it.
1237             $this->update_plan($plan2->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1238             $this->fail('The user can not update their own plan without permissions.');
1239         } catch (required_capability_exception $e) {
1240             $this->assertRegexp('/Manage learning plans./', $e->getMessage());
1241         }
1242     }
1244     /**
1245      * Test complete plan.
1246      */
1247     public function test_complete_plan() {
1248         $syscontext = context_system::instance();
1250         $this->setUser($this->creator);
1252         $this->setUser($this->user);
1254         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1255         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1256         accesslib_clear_all_caches_for_unit_testing();
1258         $this->setUser($this->user);
1260         $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1262         $result = external::complete_plan($plan->id);
1263         $this->assertTrue($result);
1264     }
1266     /**
1267      * Test reopen plan.
1268      */
1269     public function test_reopen_plan() {
1270         $syscontext = context_system::instance();
1272         $this->setUser($this->creator);
1274         $this->setUser($this->user);
1276         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1277         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1278         accesslib_clear_all_caches_for_unit_testing();
1280         $this->setUser($this->user);
1282         $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1283         external::complete_plan($plan->id);
1285         $result = external::reopen_plan($plan->id);
1286         $this->assertTrue($result);
1287     }
1289     /**
1290      * Test that we can read plans.
1291      */
1292     public function test_read_plans() {
1293         global $OUTPUT;
1294         $this->setUser($this->creator);
1296         $syscontext = context_system::instance();
1298         $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1299         $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1300         $plan3 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1301         external::complete_plan($plan3->id);
1302         $plan3 = (object) external::read_plan($plan3->id);
1304         $data = external::read_plan($plan1->id);
1305         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1306         $data = external::read_plan($plan2->id);
1307         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1308         $data = external::read_plan($plan3->id);
1309         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1311         $this->setUser($this->user);
1313         // The normal user can not edit these plans.
1314         $plan1->canmanage = false;
1315         $plan2->canmanage = false;
1316         $plan3->canmanage = false;
1317         $plan1->canbeedited = false;
1318         $plan2->canbeedited = false;
1319         $plan3->canbeedited = false;
1320         $plan1->canrequestreview = true;
1321         $plan2->canrequestreview = true;
1322         $plan3->canrequestreview = true;
1323         $plan1->canreview = false;
1324         $plan2->canreview = false;
1325         $plan3->canreview = false;
1326         $plan1->iscompleteallowed = false;
1327         $plan2->iscompleteallowed = false;
1328         $plan3->iscompleteallowed = false;
1329         $plan1->isrequestreviewallowed = true;
1330         $plan2->isrequestreviewallowed = true;
1331         $plan3->isrequestreviewallowed = true;
1332         $plan1->isapproveallowed = false;
1333         $plan2->isapproveallowed = false;
1334         $plan3->isapproveallowed = false;
1335         $plan1->isunapproveallowed = false;
1336         $plan2->isunapproveallowed = false;
1337         $plan3->isunapproveallowed = false;
1338         $plan3->isreopenallowed = false;
1339         $plan1->commentarea['canpost'] = false;
1340         $plan1->commentarea['canview'] = true;
1342         // Prevent the user from seeing their own non-draft plans.
1343         assign_capability('moodle/competency:plancommentown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1344         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1345         assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1346         accesslib_clear_all_caches_for_unit_testing();
1348         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1350         try {
1351             external::read_plan($plan2->id);
1352             $this->fail('Exception expected due to not permissions to read plan');
1353         } catch (moodle_exception $e) {
1354             $this->assertEquals('nopermissions', $e->errorcode);
1355         }
1356         try {
1357             external::read_plan($plan3->id);
1358             $this->fail('Exception expected due to not permissions to read plan');
1359         } catch (moodle_exception $e) {
1360             $this->assertEquals('nopermissions', $e->errorcode);
1361         }
1363         // Allow user to see their plan.
1364         assign_capability('moodle/competency:plancommentown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1365         assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1366         assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1367         accesslib_clear_all_caches_for_unit_testing();
1369         $plan1->commentarea['canpost'] = true;
1370         $plan1->commentarea['canview'] = true;
1371         $plan2->commentarea['canpost'] = true;
1372         $plan2->isrequestreviewallowed = false;
1373         $plan3->commentarea['canpost'] = true;
1374         $plan3->isrequestreviewallowed = false;
1375         $plan1->commentarea['canpostorhascomments'] = true;
1376         $plan2->commentarea['canpostorhascomments'] = true;
1377         $plan3->commentarea['canpostorhascomments'] = true;
1379         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1380         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1381         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1383         // Allow use to manage their own draft plan.
1384         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1385         assign_capability('moodle/competency:planmanageown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1386         assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1387         accesslib_clear_all_caches_for_unit_testing();
1389         $plan1->canmanage = true;
1390         $plan1->canbeedited = true;
1391         $plan1->canrequestreview = true;
1392         $plan1->isrequestreviewallowed = true;
1393         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1394         try {
1395             external::read_plan($plan2->id);
1396             $this->fail('Exception expected due to not permissions to read plan');
1397         } catch (moodle_exception $e) {
1398             $this->assertEquals('nopermissions', $e->errorcode);
1399         }
1400         try {
1401             external::read_plan($plan3->id);
1402             $this->fail('Exception expected due to not permissions to read plan');
1403         } catch (moodle_exception $e) {
1404             $this->assertEquals('nopermissions', $e->errorcode);
1405         }
1407         // Allow use to manage their plan.
1408         assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1409         assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1410         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1411         accesslib_clear_all_caches_for_unit_testing();
1413         $plan1->canmanage = false;
1414         $plan1->canbeedited = false;
1415         $plan1->canrequestreview = true;
1416         $plan1->canreview = true;
1417         $plan1->isrequestreviewallowed = true;
1418         $plan1->isapproveallowed = true;
1419         $plan1->iscompleteallowed = false;
1421         $plan2->canmanage = true;
1422         $plan2->canbeedited = true;
1423         $plan2->canreview = true;
1424         $plan2->iscompleteallowed = true;
1425         $plan2->isunapproveallowed = true;
1427         $plan3->canmanage = true;
1428         $plan3->canreview = true;
1429         $plan3->isreopenallowed = true;
1431         $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1432         $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1433         $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1434     }
1436     public function test_delete_plans() {
1437         $this->setUser($this->creator);
1439         $syscontext = context_system::instance();
1441         $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1442         $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1443         $plan3 = $this->create_plan(3, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1445         $this->assertTrue(external::delete_plan($plan1->id));
1447         unassign_capability('moodle/competency:planmanage', $this->creatorrole, $syscontext->id);
1448         accesslib_clear_all_caches_for_unit_testing();
1450         try {
1451             external::delete_plan($plan2->id);
1452             $this->fail('Exception expected due to not permissions to manage plans');
1453         } catch (moodle_exception $e) {
1454             $this->assertEquals('nopermissions', $e->errorcode);
1455         }
1457         $this->setUser($this->user);
1459         // Can not delete plans created by other users.
1460         try {
1461             external::delete_plan($plan2->id);
1462             $this->fail('Exception expected due to not permissions to manage plans');
1463         } catch (moodle_exception $e) {
1464             $this->assertEquals('nopermissions', $e->errorcode);
1465         }
1467         assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1468         accesslib_clear_all_caches_for_unit_testing();
1470         $this->assertTrue(external::delete_plan($plan2->id));
1472         // Can not delete plans created for other users.
1473         try {
1474             external::delete_plan($plan3->id);
1475             $this->fail('Exception expected due to not permissions to manage plans');
1476         } catch (moodle_exception $e) {
1477             $this->assertEquals('nopermissions', $e->errorcode);
1478         }
1480         $plan4 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1481         $this->assertTrue(external::delete_plan($plan4->id));
1482     }
1484     public function test_delete_plan_removes_relations() {
1485         $this->setAdminUser();
1486         $dg = $this->getDataGenerator();
1487         $lpg = $dg->get_plugin_generator('core_competency');
1489         $user = $dg->create_user();
1490         $plan = $lpg->create_plan(array('userid' => $user->id));
1491         $framework = $lpg->create_framework();
1492         $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1493         $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1494         $comp3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1495         $pc1 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp1->get_id()));
1496         $pc2 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp2->get_id()));
1497         $pc3 = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $comp3->get_id()));
1499         // Complete the plan to generate user_competency_plan entries.
1500         api::complete_plan($plan);
1502         // Confirm the data we have.
1503         $this->assertEquals(3, plan_competency::count_records(array('planid' => $plan->get_id())));
1504         $this->assertEquals(3, user_competency_plan::count_records(array('planid' => $plan->get_id(), 'userid' => $user->id)));
1506         // Delete the plan now.
1507         api::delete_plan($plan->get_id());
1508         $this->assertEquals(0, plan_competency::count_records(array('planid' => $plan->get_id())));
1509         $this->assertEquals(0, user_competency_plan::count_records(array('planid' => $plan->get_id(), 'userid' => $user->id)));
1510     }
1512     public function test_list_plan_competencies() {
1513         $this->setUser($this->creator);
1515         $dg = $this->getDataGenerator();
1516         $lpg = $dg->get_plugin_generator('core_competency');
1518         $f1 = $lpg->create_framework();
1519         $f2 = $lpg->create_framework();
1521         $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1522         $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1523         $c1c = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1524         $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1525         $c2b = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
1527         $tpl = $lpg->create_template();
1528         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1a->get_id()));
1529         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1c->get_id()));
1530         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2b->get_id()));
1532         $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id()));
1534         $uc1a = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1a->get_id(),
1535             'status' => user_competency::STATUS_IN_REVIEW, 'reviewerid' => $this->creator->id));
1536         $uc1b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1b->get_id()));
1537         $uc2b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2b->get_id(),
1538             'grade' => 2, 'proficiency' => 1));
1539         $ux1a = $lpg->create_user_competency(array('userid' => $this->creator->id, 'competencyid' => $c1a->get_id()));
1541         $result = external::list_plan_competencies($plan->get_id());
1542         $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1544         $this->assertCount(3, $result);
1545         $this->assertEquals($c1a->get_id(), $result[0]['competency']['id']);
1546         $this->assertEquals($this->user->id, $result[0]['usercompetency']['userid']);
1547         $this->assertArrayNotHasKey('usercompetencyplan', $result[0]);
1548         $this->assertEquals($c1c->get_id(), $result[1]['competency']['id']);
1549         $this->assertEquals($this->user->id, $result[1]['usercompetency']['userid']);
1550         $this->assertArrayNotHasKey('usercompetencyplan', $result[1]);
1551         $this->assertEquals($c2b->get_id(), $result[2]['competency']['id']);
1552         $this->assertEquals($this->user->id, $result[2]['usercompetency']['userid']);
1553         $this->assertArrayNotHasKey('usercompetencyplan', $result[2]);
1554         $this->assertEquals(user_competency::STATUS_IN_REVIEW, $result[0]['usercompetency']['status']);
1555         $this->assertEquals(null, $result[1]['usercompetency']['grade']);
1556         $this->assertEquals(2, $result[2]['usercompetency']['grade']);
1557         $this->assertEquals(1, $result[2]['usercompetency']['proficiency']);
1559         // Check the return values when the plan status is complete.
1560         $completedplan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id(),
1561                 'status' => plan::STATUS_COMPLETE));
1563         $uc1a = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1a->get_id(),
1564                 'planid' => $completedplan->get_id()));
1565         $uc1b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1c->get_id(),
1566                 'planid' => $completedplan->get_id()));
1567         $uc2b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c2b->get_id(),
1568                 'planid' => $completedplan->get_id(), 'grade' => 2, 'proficiency' => 1));
1569         $ux1a = $lpg->create_user_competency_plan(array('userid' => $this->creator->id, 'competencyid' => $c1a->get_id(),
1570                 'planid' => $completedplan->get_id()));
1572         $result = external::list_plan_competencies($completedplan->get_id());
1573         $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1575         $this->assertCount(3, $result);
1576         $this->assertEquals($c1a->get_id(), $result[0]['competency']['id']);
1577         $this->assertEquals($this->user->id, $result[0]['usercompetencyplan']['userid']);
1578         $this->assertArrayNotHasKey('usercompetency', $result[0]);
1579         $this->assertEquals($c1c->get_id(), $result[1]['competency']['id']);
1580         $this->assertEquals($this->user->id, $result[1]['usercompetencyplan']['userid']);
1581         $this->assertArrayNotHasKey('usercompetency', $result[1]);
1582         $this->assertEquals($c2b->get_id(), $result[2]['competency']['id']);
1583         $this->assertEquals($this->user->id, $result[2]['usercompetencyplan']['userid']);
1584         $this->assertArrayNotHasKey('usercompetency', $result[2]);
1585         $this->assertEquals(null, $result[1]['usercompetencyplan']['grade']);
1586         $this->assertEquals(2, $result[2]['usercompetencyplan']['grade']);
1587         $this->assertEquals(1, $result[2]['usercompetencyplan']['proficiency']);
1588     }
1590     public function test_add_competency_to_template() {
1591         $this->setUser($this->creator);
1593         $syscontext = context_system::instance();
1595         // Create a template.
1596         $template = $this->create_template(1, true);
1598         // Create a competency.
1599         $framework = $this->create_competency_framework(1, true);
1600         $competency = $this->create_competency(1, $framework->id);
1602         // Add the competency.
1603         external::add_competency_to_template($template->id, $competency->id);
1605         // Check that it was added.
1606         $this->assertEquals(1, external::count_competencies_in_template($template->id));
1608         // Unassign capability.
1609         unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1610         accesslib_clear_all_caches_for_unit_testing();
1612         // Check we can not add the competency now.
1613         try {
1614             external::add_competency_to_template($template->id, $competency->id);
1615             $this->fail('Exception expected due to not permissions to manage template competencies');
1616         } catch (moodle_exception $e) {
1617             $this->assertEquals('nopermissions', $e->errorcode);
1618         }
1619     }
1621     public function test_remove_competency_from_template() {
1622         $syscontext = context_system::instance();
1623         $this->setUser($this->creator);
1624         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1626         // Create a template.
1627         $template = $this->create_template(1, true);
1629         // Create a competency.
1630         $framework = $lpg->create_framework();
1631         $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1633         // Add the competency.
1634         external::add_competency_to_template($template->id, $competency->get_id());
1636         // Check that it was added.
1637         $this->assertEquals(1, external::count_competencies_in_template($template->id));
1639         // Check that we can remove the competency.
1640         external::remove_competency_from_template($template->id, $competency->get_id());
1642         // Check that it was removed.
1643         $this->assertEquals(0, external::count_competencies_in_template($template->id));
1645         // Unassign capability.
1646         unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1647         accesslib_clear_all_caches_for_unit_testing();
1649         // Check we can not remove the competency now.
1650         try {
1651             external::add_competency_to_template($template->id, $competency->get_id());
1652             $this->fail('Exception expected due to not permissions to manage template competencies');
1653         } catch (moodle_exception $e) {
1654             $this->assertEquals('nopermissions', $e->errorcode);
1655         }
1656     }
1658     /**
1659      * Test we can re-order competency frameworks.
1660      */
1661     public function test_reorder_template_competencies() {
1662         $this->setUser($this->creator);
1664         $syscontext = context_system::instance();
1665         $onehour = time() + 60 * 60;
1667         // Create a template.
1668         $template = $this->create_template(1, true);
1670         // Create a competency framework.
1671         $framework = $this->create_competency_framework(1, true);
1673         // Create multiple competencies.
1674         $competency1 = $this->create_competency(1, $framework->id);
1675         $competency2 = $this->create_competency(2, $framework->id);
1676         $competency3 = $this->create_competency(3, $framework->id);
1677         $competency4 = $this->create_competency(4, $framework->id);
1679         // Add the competencies.
1680         external::add_competency_to_template($template->id, $competency1->id);
1681         external::add_competency_to_template($template->id, $competency2->id);
1682         external::add_competency_to_template($template->id, $competency3->id);
1683         external::add_competency_to_template($template->id, $competency4->id);
1685         // Test if removing competency from template don't create sortorder holes.
1686         external::remove_competency_from_template($template->id, $competency3->id);
1687         $templcomp4 = template_competency::get_record(array(
1688             'templateid' => $template->id,
1689             'competencyid' => $competency4->id
1690         ));
1692         $this->assertEquals(2, $templcomp4->get_sortorder());
1694         // This is a move up.
1695         external::reorder_template_competency($template->id, $competency4->id, $competency2->id);
1696         $result = external::list_competencies_in_template($template->id);
1697         $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1699         $r1 = (object) $result[0];
1700         $r2 = (object) $result[1];
1701         $r3 = (object) $result[2];
1703         $this->assertEquals($competency1->id, $r1->id);
1704         $this->assertEquals($competency4->id, $r2->id);
1705         $this->assertEquals($competency2->id, $r3->id);
1707         // This is a move down.
1708         external::reorder_template_competency($template->id, $competency1->id, $competency4->id);
1709         $result = external::list_competencies_in_template($template->id);
1710         $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1712         $r1 = (object) $result[0];
1713         $r2 = (object) $result[1];
1714         $r3 = (object) $result[2];
1716         $this->assertEquals($competency4->id, $r1->id);
1717         $this->assertEquals($competency1->id, $r2->id);
1718         $this->assertEquals($competency2->id, $r3->id);
1720         $this->setExpectedException('required_capability_exception');
1721         $this->setUser($this->user);
1722         external::reorder_template_competency($template->id, $competency1->id, $competency2->id);
1723     }
1725     /**
1726      * Test we can duplicate learning plan template.
1727      */
1728     public function test_duplicate_learning_plan_template() {
1729         $this->setUser($this->creator);
1731         $syscontext = context_system::instance();
1732         $onehour = time() + 60 * 60;
1734         // Create a template.
1735         $template = $this->create_template(1, true);
1737         // Create a competency framework.
1738         $framework = $this->create_competency_framework(1, true);
1740         // Create multiple competencies.
1741         $competency1 = $this->create_competency(1, $framework->id);
1742         $competency2 = $this->create_competency(2, $framework->id);
1743         $competency3 = $this->create_competency(3, $framework->id);
1745         // Add the competencies.
1746         external::add_competency_to_template($template->id, $competency1->id);
1747         external::add_competency_to_template($template->id, $competency2->id);
1748         external::add_competency_to_template($template->id, $competency3->id);
1750         // Duplicate the learning plan template.
1751         $duplicatedtemplate = external::duplicate_template($template->id);
1753         $result = external::list_competencies_in_template($template->id);
1754         $resultduplicated = external::list_competencies_in_template($duplicatedtemplate->id);
1756         $this->assertEquals(count($result), count($resultduplicated));
1757         $this->assertContains($template->shortname, $duplicatedtemplate->shortname);
1758         $this->assertEquals($duplicatedtemplate->description, $template->description);
1759         $this->assertEquals($duplicatedtemplate->descriptionformat, $template->descriptionformat);
1760         $this->assertEquals($duplicatedtemplate->visible, $template->visible);
1761     }
1763     /**
1764      * Test that we can return scale values for a scale with the scale ID.
1765      */
1766     public function test_get_scale_values() {
1767         global $DB;
1769         $this->setUser($this->creator);
1771         // Create a scale.
1772         $record = new stdClass();
1773         $record->courseid = 0;
1774         $record->userid = $this->creator->id;
1775         $record->name = 'Test scale';
1776         $record->scale = 'Poor, Not good, Okay, Fine, Excellent';
1777         $record->description = '<p>Test scale description.</p>';
1778         $record->descriptionformat = 1;
1779         $record->timemodified = time();
1780         $scaleid = $DB->insert_record('scale', $record);
1781         // Expected return value.
1782         $expected = array(array(
1783                 'id' => 1,
1784                 'name' => 'Poor'
1785             ), array(
1786                 'id' => 2,
1787                 'name' => 'Not good'
1788             ), array(
1789                 'id' => 3,
1790                 'name' => 'Okay'
1791             ), array(
1792                 'id' => 4,
1793                 'name' => 'Fine'
1794             ), array(
1795                 'id' => 5,
1796                 'name' => 'Excellent'
1797             )
1798         );
1799         // Call the webservice.
1800         $result = external::get_scale_values($scaleid);
1801         $this->assertEquals($expected, $result);
1802     }
1804     /**
1805      * Create a template.
1806      */
1807     public function test_create_template() {
1808         $syscontextid = context_system::instance()->id;
1809         $catcontextid = context_coursecat::instance($this->category->id)->id;
1811         // A user without permission.
1812         $this->setUser($this->user);
1813         try {
1814             $result = $this->create_template(1, true);
1815             $this->fail('Invalid permissions');
1816         } catch (required_capability_exception $e) {
1817             // All good.
1818         }
1820         // A user without permission in a category.
1821         $this->setUser($this->catuser);
1822         try {
1823             $result = $this->create_template(1, false);
1824             $this->fail('Invalid permissions');
1825         } catch (required_capability_exception $e) {
1826             // All good.
1827         }
1829         // A user with permissions in the system.
1830         $this->setUser($this->creator);
1831         $result = $this->create_template(1, true);
1832         $this->assertEquals('shortname1', $result->shortname);
1833         $this->assertEquals($syscontextid, $result->contextid);
1834         $this->assertNotEmpty($result->id);
1836         $result = $this->create_template(2, false);
1837         $this->assertEquals('shortname2', $result->shortname);
1838         $this->assertEquals($catcontextid, $result->contextid);
1839         $this->assertNotEmpty($result->id);
1841         // A user with permissions in the category.
1842         $this->setUser($this->catcreator);
1843         try {
1844             $result = $this->create_template(3, true);
1845             $this->fail('Invalid permissions');
1846         } catch (required_capability_exception $e) {
1847             // All good.
1848         }
1850         $result = $this->create_template(3, false);
1851         $this->assertEquals('shortname3', $result->shortname);
1852         $this->assertEquals($catcontextid, $result->contextid);
1853         $this->assertNotEmpty($result->id);
1854     }
1856     /**
1857      * Read a template.
1858      */
1859     public function test_read_template() {
1860         $syscontextid = context_system::instance()->id;
1861         $catcontextid = context_coursecat::instance($this->category->id)->id;
1863         // Set a due date for the next year.
1864         $date = new DateTime('now');
1865         $date->modify('+1 year');
1866         $duedate = $date->getTimestamp();
1868         // Creating two templates.
1869         $this->setUser($this->creator);
1870         $systemplate = $this->create_template(1, true);
1871         $cattemplate = $this->create_template(2, false);
1873         // User without permissions to read in system.
1874         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
1875         accesslib_clear_all_caches_for_unit_testing();
1876         $this->setUser($this->user);
1877         $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1878         try {
1879             external::read_template($systemplate->id);
1880             $this->fail('Invalid permissions');
1881         } catch (required_capability_exception $e) {
1882             // All good.
1883         }
1884         try {
1885             external::read_template($cattemplate->id);
1886             $this->fail('Invalid permissions');
1887         } catch (required_capability_exception $e) {
1888             // All good.
1889         }
1891         // User with permissions to read in a category.
1892         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
1893         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
1894         accesslib_clear_all_caches_for_unit_testing();
1895         $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1896         $this->assertTrue(has_capability('moodle/competency:templateview', context_coursecat::instance($this->category->id)));
1897         try {
1898             external::read_template($systemplate->id);
1899             $this->fail('Invalid permissions');
1900         } catch (required_capability_exception $e) {
1901             // All good.
1902         }
1904         $result = external::read_template($cattemplate->id);
1905         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1906         $this->assertEquals($cattemplate->id, $result['id']);
1907         $this->assertEquals('shortname2', $result['shortname']);
1908         $this->assertEquals('description2', $result['description']);
1909         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1910         $this->assertEquals(1, $result['visible']);
1911         $this->assertEquals(0, $result['duedate']);
1912         $this->assertEquals(userdate(0), $result['duedateformatted']);
1914         // User with permissions to read in the system.
1915         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
1916         accesslib_clear_all_caches_for_unit_testing();
1917         $this->assertTrue(has_capability('moodle/competency:templateview', context_system::instance()));
1918         $result = external::read_template($systemplate->id);
1919         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1920         $this->assertEquals($systemplate->id, $result['id']);
1921         $this->assertEquals('shortname1', $result['shortname']);
1922         $this->assertEquals('description1', $result['description']);
1923         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1924         $this->assertEquals(true, $result['visible']);
1925         $this->assertEquals(0, $result['duedate']);
1926         $this->assertEquals(userdate(0), $result['duedateformatted']);
1928         $result = external::read_template($cattemplate->id);
1929         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1930         $this->assertEquals($cattemplate->id, $result['id']);
1931         $this->assertEquals('shortname2', $result['shortname']);
1932         $this->assertEquals('description2', $result['description']);
1933         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1934         $this->assertEquals(true, $result['visible']);
1935         $this->assertEquals(0, $result['duedate']);
1936         $this->assertEquals(userdate(0), $result['duedateformatted']);
1937     }
1939     /**
1940      * Update a template.
1941      */
1942     public function test_update_template() {
1943         $syscontextid = context_system::instance()->id;
1944         $catcontextid = context_coursecat::instance($this->category->id)->id;
1946         // Set a due date for the next year.
1947         $date = new DateTime('now');
1948         $date->modify('+1 year');
1949         $duedate = $date->getTimestamp();
1951         // Creating two templates.
1952         $this->setUser($this->creator);
1953         $systemplate = $this->create_template(1, true);
1954         $cattemplate = $this->create_template(2, false);
1956         // Trying to update in a without permissions.
1957         $this->setUser($this->user);
1958         try {
1959             $this->update_template($systemplate->id, 3);
1960             $this->fail('Invalid permissions');
1961         } catch (required_capability_exception $e) {
1962             // All good.
1963         }
1965         try {
1966             $this->update_template($cattemplate->id, 3);
1967             $this->fail('Invalid permissions');
1968         } catch (required_capability_exception $e) {
1969             // All good.
1970         }
1972         // User with permissions to update in category.
1973         $this->setUser($this->catcreator);
1974         try {
1975             $this->update_template($systemplate->id, 3);
1976             $this->fail('Invalid permissions');
1977         } catch (required_capability_exception $e) {
1978             // All good.
1979         }
1981         $result = $this->update_template($cattemplate->id, 3);
1982         $this->assertTrue($result);
1983         $result = external::read_template($cattemplate->id);
1984         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1985         $this->assertEquals($cattemplate->id, $result['id']);
1986         $this->assertEquals('shortname3', $result['shortname']);
1987         $this->assertEquals("description3", $result['description']);
1988         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1989         $this->assertEquals(true, $result['visible']);
1990         $this->assertEquals(0, $result['duedate']);
1991         $this->assertEquals(userdate(0), $result['duedateformatted']);
1993         // User with permissions to update in the system.
1994         $this->setUser($this->creator);
1995         $result = $this->update_template($systemplate->id, 4);
1996         $this->assertTrue($result);
1997         $result = external::read_template($systemplate->id);
1998         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1999         $this->assertEquals($systemplate->id, $result['id']);
2000         $this->assertEquals('shortname4', $result['shortname']);
2001         $this->assertEquals('description4', $result['description']);
2002         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
2003         $this->assertEquals(true, $result['visible']);
2004         $this->assertEquals(0, $result['duedate']);
2005         $this->assertEquals(userdate(0), $result['duedateformatted']);
2007         $result = $this->update_template($cattemplate->id, 5);
2008         $this->assertTrue($result);
2009         $result = external::read_template($cattemplate->id);
2010         $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
2011         $this->assertEquals($cattemplate->id, $result['id']);
2012         $this->assertEquals('shortname5', $result['shortname']);
2013         $this->assertEquals('description5', $result['description']);
2014         $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
2015         $this->assertEquals(1, $result['visible']);
2016         $this->assertEquals(0, $result['duedate']);
2017         $this->assertEquals(userdate(0), $result['duedateformatted']);
2018     }
2020     /**
2021      * Delete a template.
2022      */
2023     public function test_delete_template() {
2024         global $DB;
2025         $syscontextid = context_system::instance()->id;
2026         $catcontextid = context_coursecat::instance($this->category->id)->id;
2028         // Creating a few templates.
2029         $this->setUser($this->creator);
2030         $sys1 = $this->create_template(1, true);
2031         $cat1 = $this->create_template(2, false);
2032         $cat2 = $this->create_template(3, false);
2033         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2034         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2035         $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2037         // User without permissions.
2038         $this->setUser($this->user);
2039         try {
2040             external::delete_template($sys1->id);
2041             $this->fail('Invalid permissions');
2042         } catch (required_capability_exception $e) {
2043             // All good.
2044         }
2045         try {
2046             external::delete_template($cat1->id);
2047             $this->fail('Invalid permissions');
2048         } catch (required_capability_exception $e) {
2049             // All good.
2050         }
2052         // User with category permissions.
2053         $this->setUser($this->catcreator);
2054         try {
2055             external::delete_template($sys1->id);
2056             $this->fail('Invalid permissions');
2057         } catch (required_capability_exception $e) {
2058             // All good.
2059         }
2061         $result = external::delete_template($cat1->id);
2062         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2063         $this->assertTrue($result);
2064         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2066         // User with system permissions.
2067         $this->setUser($this->creator);
2068         $result = external::delete_template($sys1->id);
2069         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2070         $this->assertTrue($result);
2071         $result = external::delete_template($cat2->id);
2072         $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2073         $this->assertTrue($result);
2074         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2075         $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2076     }
2078     /**
2079      * List templates.
2080      */
2081     public function test_list_templates() {
2082         $syscontextid = context_system::instance()->id;
2083         $catcontextid = context_coursecat::instance($this->category->id)->id;
2085         // Creating a few templates.
2086         $this->setUser($this->creator);
2087         $sys1 = $this->create_template(1, true);
2088         $sys2 = $this->create_template(2, true);
2089         $cat1 = $this->create_template(3, false);
2090         $cat2 = $this->create_template(4, false);
2092         // User without permission.
2093         $this->setUser($this->user);
2094         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2095         accesslib_clear_all_caches_for_unit_testing();
2096         try {
2097             external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2098             $this->fail('Invalid permissions');
2099         } catch (required_capability_exception $e) {
2100             // All good.
2101         }
2103         // User with category permissions.
2104         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2105         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2106         accesslib_clear_all_caches_for_unit_testing();
2107         $result = external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2108         $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2109         $this->assertCount(2, $result);
2110         $this->assertEquals($cat1->id, $result[0]['id']);
2111         $this->assertEquals($cat2->id, $result[1]['id']);
2113         // User with system permissions.
2114         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2115         accesslib_clear_all_caches_for_unit_testing();
2116         $result = external::list_templates('id', 'DESC', 0, 3, array('contextid' => $catcontextid), 'parents', false);
2117         $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2118         $this->assertCount(3, $result);
2119         $this->assertEquals($cat2->id, $result[0]['id']);
2120         $this->assertEquals($cat1->id, $result[1]['id']);
2121         $this->assertEquals($sys2->id, $result[2]['id']);
2122     }
2124     /**
2125      * List templates using competency.
2126      */
2127     public function test_list_templates_using_competency() {
2128         $this->setUser($this->creator);
2130         // Create a template.
2131         $template1 = $this->create_template(1, true);
2132         $template2 = $this->create_template(2, true);
2133         $template3 = $this->create_template(3, true);
2134         $template4 = $this->create_template(4, true);
2136         // Create a competency.
2137         $framework = $this->create_competency_framework(1, true);
2138         $competency1 = $this->create_competency(1, $framework->id);
2139         $competency2 = $this->create_competency(2, $framework->id);
2141         // Add the competency.
2142         external::add_competency_to_template($template1->id, $competency1->id);
2143         external::add_competency_to_template($template2->id, $competency1->id);
2144         external::add_competency_to_template($template3->id, $competency1->id);
2146         external::add_competency_to_template($template4->id, $competency2->id);
2148         $listcomp1 = external::list_templates_using_competency($competency1->id);
2149         $listcomp2 = external::list_templates_using_competency($competency2->id);
2151         // Test count_templates_using_competency.
2152         $counttempcomp1 = external::count_templates_using_competency($competency1->id);
2153         $counttempcomp2 = external::count_templates_using_competency($competency2->id);
2155         $comptemp1 = $listcomp1[0];
2156         $comptemp2 = $listcomp1[1];
2157         $comptemp3 = $listcomp1[2];
2159         $comptemp4 = $listcomp2[0];
2161         $this->assertCount(3, $listcomp1);
2162         $this->assertCount(1, $listcomp2);
2163         $this->assertEquals(3, $counttempcomp1);
2164         $this->assertEquals(1, $counttempcomp2);
2165         $this->assertEquals($template1->id, $comptemp1->id);
2166         $this->assertEquals($template2->id, $comptemp2->id);
2167         $this->assertEquals($template3->id, $comptemp3->id);
2168         $this->assertEquals($template4->id, $comptemp4->id);
2169     }
2171     public function test_count_templates() {
2172         $syscontextid = context_system::instance()->id;
2173         $catcontextid = context_coursecat::instance($this->category->id)->id;
2175         // Creating a few templates.
2176         $this->setUser($this->creator);
2177         $sys1 = $this->create_template(1, true);
2178         $sys2 = $this->create_template(2, true);
2179         $cat1 = $this->create_template(3, false);
2180         $cat2 = $this->create_template(4, false);
2181         $cat3 = $this->create_template(5, false);
2183         // User without permission.
2184         $this->setUser($this->user);
2185         assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2186         accesslib_clear_all_caches_for_unit_testing();
2187         try {
2188             external::count_templates(array('contextid' => $syscontextid), 'children');
2189             $this->fail('Invalid permissions');
2190         } catch (required_capability_exception $e) {
2191             // All good.
2192         }
2194         // User with category permissions.
2195         assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2196         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2197         accesslib_clear_all_caches_for_unit_testing();
2198         $result = external::count_templates(array('contextid' => $syscontextid), 'children');
2199         $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2200         $this->assertEquals(3, $result);
2202         // User with system permissions.
2203         assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2204         accesslib_clear_all_caches_for_unit_testing();
2205         $result = external::count_templates(array('contextid' => $catcontextid), 'parents');
2206         $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2207         $this->assertEquals(5, $result);
2208     }
2210     /**
2211      * Test that we can add related competencies.
2212      *
2213      * @return void
2214      */
2215     public function test_add_related_competency() {
2216         global $DB;
2217         $this->setUser($this->creator);
2219         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2220         $framework = $lpg->create_framework();
2221         $framework2 = $lpg->create_framework();
2222         $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2223         $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2224         $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2225         $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework2->get_id()));
2227         // The lower one always as competencyid.
2228         $result = external::add_related_competency($competency1->get_id(), $competency2->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' => $competency2->get_id()
2236             )
2237         ));
2238         $this->assertFalse($DB->record_exists_select(
2239             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2240             array(
2241                 'cid' => $competency2->get_id(),
2242                 'rid' => $competency1->get_id()
2243             )
2244         ));
2246         $result = external::add_related_competency($competency3->get_id(), $competency1->get_id());
2247         $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2248         $this->assertTrue($result);
2249         $this->assertTrue($DB->record_exists_select(
2250             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2251             array(
2252                 'cid' => $competency1->get_id(),
2253                 'rid' => $competency3->get_id()
2254             )
2255         ));
2256         $this->assertFalse($DB->record_exists_select(
2257             related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2258             array(
2259                 'cid' => $competency3->get_id(),
2260                 'rid' => $competency1->get_id()
2261             )
2262         ));
2264         // We can not allow a duplicate relation, not even in the other direction.
2265         $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2266             'competencyid = :cid AND relatedcompetencyid = :rid',
2267             array('cid' => $competency1->get_id(), 'rid' => $competency2->get_id())));
2268         $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2269             'competencyid = :cid AND relatedcompetencyid = :rid',
2270             array('rid' => $competency1->get_id(), 'cid' => $competency2->get_id())));
2271         $result = external::add_related_competency($competency2->get_id(), $competency1->get_id());
2272         $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2273         $this->assertTrue($result);
2274         $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2275             'competencyid = :cid AND relatedcompetencyid = :rid',
2276             array('cid' => $competency1->get_id(), 'rid' => $competency2->get_id())));
2277         $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2278             'competencyid = :cid AND relatedcompetencyid = :rid',
2279             array('rid' => $competency1->get_id(), 'cid' => $competency2->get_id())));
2281         // Check that we cannot create links across frameworks.
2282         try {
2283             external::add_related_competency($competency1->get_id(), $competency4->get_id());
2284             $this->fail('Exception expected due mis-use of shared competencies');
2285         } catch (invalid_persistent_exception $e) {
2286             // Yay!
2287         }
2289         // User without permission.
2290         $this->setUser($this->user);
2292         // Check we can not add the related competency now.
2293         try {
2294             external::add_related_competency($competency1->get_id(), $competency3->get_id());
2295             $this->fail('Exception expected due to not permissions to manage template competencies');
2296         } catch (moodle_exception $e) {
2297             $this->assertEquals('nopermissions', $e->errorcode);
2298         }
2300     }
2302     /**
2303      * Test that we can remove related competencies.
2304      *
2305      * @return void
2306      */
2307     public function test_remove_related_competency() {
2308         $this->setUser($this->creator);
2310         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2311         $framework = $lpg->create_framework();
2312         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2313         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2314         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2315         $rc1 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c2->get_id()));
2316         $rc2 = $lpg->create_related_competency(array('competencyid' => $c2->get_id(), 'relatedcompetencyid' => $c3->get_id()));
2318         $this->assertEquals(2, related_competency::count_records());
2320         // Returns false when the relation does not exist.
2321         $result = external::remove_related_competency($c1->get_id(), $c3->get_id());
2322         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2323         $this->assertFalse($result);
2325         // Returns true on success.
2326         $result = external::remove_related_competency($c2->get_id(), $c3->get_id());
2327         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2328         $this->assertTrue($result);
2329         $this->assertEquals(1, related_competency::count_records());
2331         // We don't need to specify competencyid and relatedcompetencyid in the right order.
2332         $result = external::remove_related_competency($c2->get_id(), $c1->get_id());
2333         $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2334         $this->assertTrue($result);
2335         $this->assertEquals(0, related_competency::count_records());
2336     }
2338     /**
2339      * Test that we can search and include related competencies.
2340      *
2341      * @return void
2342      */
2343     public function test_search_competencies_including_related() {
2344         $this->setUser($this->creator);
2346         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2347         $framework = $lpg->create_framework();
2348         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2349         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2350         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2351         $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2352         $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2354         // We have 1-2, 1-3, 2-4, and no relation between 2-3 nor 1-4 nor 5.
2355         $rc12 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c2->get_id()));
2356         $rc13 = $lpg->create_related_competency(array('competencyid' => $c1->get_id(), 'relatedcompetencyid' => $c3->get_id()));
2357         $rc24 = $lpg->create_related_competency(array('competencyid' => $c2->get_id(), 'relatedcompetencyid' => $c4->get_id()));
2359         $result = external::search_competencies('comp', $framework->get_id(), true);
2360         $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
2362         $this->assertCount(5, $result);
2364     }
2366     /**
2367      * Test that we can add competency to plan if we have the right capability.
2368      *
2369      * @return void
2370      */
2371     public function test_add_competency_to_plan() {
2372         $this->resetAfterTest(true);
2373         $dg = $this->getDataGenerator();
2374         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2375         $usermanage = $dg->create_user();
2376         $user = $dg->create_user();
2378         $syscontext = context_system::instance();
2380         // Creating specific roles.
2381         $managerole = $dg->create_role(array(
2382             'name' => 'User manage',
2383             'shortname' => 'manage'
2384         ));
2386         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2387         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2389         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2391         $this->setUser($usermanage);
2392         $plan = array (
2393             'userid' => $usermanage->id,
2394             'status' => \core_competency\plan::STATUS_ACTIVE
2395         );
2396         $pl1 = $lpg->create_plan($plan);
2397         $framework = $lpg->create_framework();
2398         $competency = $lpg->create_competency(
2399                 array('competencyframeworkid' => $framework->get_id())
2400                 );
2401         $this->assertTrue(external::add_competency_to_plan($pl1->get_id(), $competency->get_id()));
2403         // A competency cannot be added to plan based on template.
2404         $template = $lpg->create_template();
2405         $plan = array (
2406             'userid' => $usermanage->id,
2407             'status' => \core_competency\plan::STATUS_ACTIVE,
2408             'templateid' => $template->get_id()
2409         );
2410         $pl2 = $lpg->create_plan($plan);
2411         try {
2412             external::add_competency_to_plan($pl2->get_id(), $competency->get_id());
2413             $this->fail('A competency cannot be added to plan based on template');
2414         } catch (coding_exception $ex) {
2415             $this->assertTrue(true);
2416         }
2418         // User without capability cannot add competency to a plan.
2419         $this->setUser($user);
2420         try {
2421             external::add_competency_to_plan($pl1->get_id(), $competency->get_id());
2422             $this->fail('User without capability cannot add competency to a plan');
2423         } catch (required_capability_exception $ex) {
2424             $this->assertTrue(true);
2425         }
2426     }
2428     /**
2429      * Test that we can add competency to plan if we have the right capability.
2430      *
2431      * @return void
2432      */
2433     public function test_remove_competency_from_plan() {
2434         $this->resetAfterTest(true);
2435         $dg = $this->getDataGenerator();
2436         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2437         $usermanage = $dg->create_user();
2438         $user = $dg->create_user();
2440         $syscontext = context_system::instance();
2442         // Creating specific roles.
2443         $managerole = $dg->create_role(array(
2444             'name' => 'User manage',
2445             'shortname' => 'manage'
2446         ));
2448         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2449         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2451         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2453         $this->setUser($usermanage);
2454         $plan = array (
2455             'userid' => $usermanage->id,
2456             'status' => \core_competency\plan::STATUS_ACTIVE
2457         );
2458         $pl1 = $lpg->create_plan($plan);
2459         $framework = $lpg->create_framework();
2460         $competency = $lpg->create_competency(
2461                 array('competencyframeworkid' => $framework->get_id())
2462                 );
2463         $lpg->create_plan_competency(
2464                 array(
2465                     'planid' => $pl1->get_id(),
2466                     'competencyid' => $competency->get_id()
2467                     )
2468                 );
2469         $this->assertTrue(external::remove_competency_from_plan($pl1->get_id(), $competency->get_id()));
2470         $this->assertCount(0, $pl1->get_competencies());
2471     }
2473     /**
2474      * Test that we can add competency to plan if we have the right capability.
2475      *
2476      * @return void
2477      */
2478     public function test_reorder_plan_competency() {
2479         $this->resetAfterTest(true);
2480         $dg = $this->getDataGenerator();
2481         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2482         $usermanage = $dg->create_user();
2483         $user = $dg->create_user();
2485         $syscontext = context_system::instance();
2487         // Creating specific roles.
2488         $managerole = $dg->create_role(array(
2489             'name' => 'User manage',
2490             'shortname' => 'manage'
2491         ));
2493         assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2494         assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2496         $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2498         $this->setUser($usermanage);
2499         $plan = array (
2500             'userid' => $usermanage->id,
2501             'status' => \core_competency\plan::STATUS_ACTIVE
2502         );
2503         $pl1 = $lpg->create_plan($plan);
2504         $framework = $lpg->create_framework();
2505         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2506         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2507         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2508         $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2509         $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2511         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c1->get_id(), 'sortorder' => 1));
2512         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c2->get_id(), 'sortorder' => 2));
2513         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c3->get_id(), 'sortorder' => 3));
2514         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c4->get_id(), 'sortorder' => 4));
2515         $lpg->create_plan_competency(array('planid' => $pl1->get_id(), 'competencyid' => $c5->get_id(), 'sortorder' => 5));
2517         // Test if removing competency from plan don't create sortorder holes.
2518         external::remove_competency_from_plan($pl1->get_id(), $c4->get_id());
2519         $plancomp5 = plan_competency::get_record(array(
2520             'planid' => $pl1->get_id(),
2521             'competencyid' => $c5->get_id()
2522         ));
2524         $this->assertEquals(3, $plancomp5->get_sortorder());
2526         $this->assertTrue(external::reorder_plan_competency($pl1->get_id(), $c2->get_id(), $c5->get_id()));
2527         $this->assertTrue(external::reorder_plan_competency($pl1->get_id(), $c3->get_id(), $c1->get_id()));
2528         $plancompetencies = plan_competency::get_records(array('planid' => $pl1->get_id()), 'sortorder', 'ASC');
2529         $plcmp1 = $plancompetencies[0];
2530         $plcmp2 = $plancompetencies[1];
2531         $plcmp3 = $plancompetencies[2];
2532         $plcmp4 = $plancompetencies[3];
2534         $this->assertEquals($plcmp1->get_competencyid(), $c3->get_id());
2535         $this->assertEquals($plcmp2->get_competencyid(), $c1->get_id());
2536         $this->assertEquals($plcmp3->get_competencyid(), $c5->get_id());
2537         $this->assertEquals($plcmp4->get_competencyid(), $c2->get_id());
2538     }
2540     /**
2541      * Test resolving sortorder when we creating competency.
2542      */
2543     public function test_fix_sortorder_when_creating_competency() {
2544         $this->resetAfterTest(true);
2545         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2546         $framework = $lpg->create_framework();
2548         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2549         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'sortorder' => 20));
2550         $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'sortorder' => 1));
2552         $this->assertEquals(0, $c1->get_sortorder());
2553         $this->assertEquals(1, $c2->get_sortorder());
2554         $this->assertEquals(2, $c3->get_sortorder());
2555     }
2557     /**
2558      * Test resolving sortorder when we delete competency.
2559      */
2560     public function test_fix_sortorder_when_delete_competency() {
2561         $this->resetAfterTest(true);
2562         $this->setUser($this->creator);
2563         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2565         $framework = $lpg->create_framework();
2567         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2568         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2569         $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2570         $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2571         $c2c = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2572         $c2d = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2574         $this->assertEquals(0, $c1->get_sortorder());
2575         $this->assertEquals(1, $c2->get_sortorder());
2576         $this->assertEquals(0, $c2a->get_sortorder());
2577         $this->assertEquals(1, $c2b->get_sortorder());
2578         $this->assertEquals(2, $c2c->get_sortorder());
2579         $this->assertEquals(3, $c2d->get_sortorder());
2581         $result = external::delete_competency($c1->get_id());
2582         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2584         $c2->read();
2585         $c2a->read();
2586         $c2b->read();
2587         $c2c->read();
2588         $c2d->read();
2590         $this->assertEquals(0, $c2->get_sortorder());
2591         $this->assertEquals(0, $c2a->get_sortorder());
2592         $this->assertEquals(1, $c2b->get_sortorder());
2593         $this->assertEquals(2, $c2c->get_sortorder());
2594         $this->assertEquals(3, $c2d->get_sortorder());
2596         $result = external::delete_competency($c2b->get_id());
2597         $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2599         $c2->read();
2600         $c2a->read();
2601         $c2c->read();
2602         $c2d->read();
2604         $this->assertEquals(0, $c2->get_sortorder());
2605         $this->assertEquals(0, $c2a->get_sortorder());
2606         $this->assertEquals(1, $c2c->get_sortorder());
2607         $this->assertEquals(2, $c2d->get_sortorder());
2608     }
2610     /**
2611      * Test resolving sortorder when moving a competency.
2612      */
2613     public function test_fix_sortorder_when_moving_competency() {
2614         $this->resetAfterTest(true);
2615         $this->setUser($this->creator);
2616         $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2618         $framework = $lpg->create_framework();
2620         $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2621         $c1a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c1->get_id()));
2622         $c1b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c1->get_id()));
2623         $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2624         $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2625         $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(), 'parentid' => $c2->get_id()));
2627         $this->assertEquals(0, $c1->get_sortorder());
2628         $this->assertEquals(0, $c1a->get_sortorder());
2629         $this->assertEquals(1, $c1b->get_sortorder());
2630         $this->assertEquals(1, $c2->get_sortorder());
2631         $this->assertEquals(0, $c2a->get_sortorder());
2632         $this->assertEquals(1, $c2b->get_sortorder());
2634         $result = external::set_parent_competency($c2a->get_id(), $c1->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(2, $c2a->get_sortorder());
2648         $this->assertEquals(1, $c2->get_sortorder());
2649         $this->assertEquals(0, $c2b->get_sortorder());
2651         // Move a root node.
2652         $result = external::set_parent_competency($c2->get_id(), $c1b->get_id());
2653         $result = external_api::clean_returnvalue(external::set_parent_competency_returns(), $result);
2655         $c1->read();
2656         $c1a->read();
2657         $c1b->read();
2658         $c2->read();
2659         $c2a->read();
2660         $c2b->read();
2662         $this->assertEquals(0, $c1->get_sortorder());
2663         $this->assertEquals(0, $c1a->get_sortorder());
2664         $this->assertEquals(1, $c1b->get_sortorder());
2665         $this->assertEquals(0, $c2->get_sortorder());
2666         $this->assertEquals(0, $c2b->get_sortorder());
2667         $this->assertEquals(2, $c2a->get_sortorder());
2668     }
2670     public function test_grade_competency_in_plan() {
2671         global $CFG;
2673         $this->setUser($this->creator);
2675         $dg = $this->getDataGenerator();
2676         $lpg = $dg->get_plugin_generator('core_competency');
2678         $f1 = $lpg->create_framework();
2680         $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2682         $tpl = $lpg->create_template();
2683         $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id()));
2685         $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get_id(), 'name' => 'Evil'));
2687         $uc = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1->get_id()));
2689         $evidence = external::grade_competency_in_plan($plan->get_id(), $c1->get_id(), 1, 'Evil note');
2691         $this->assertEquals('The competency rating was manually set in the learning plan \'Evil\'.', $evidence->description);
2692         $this->assertEquals('A', $evidence->gradename);
2693         $this->assertEquals('Evil note', $evidence->note);
2695         $this->setUser($this->user);
2697         $this->setExpectedException('required_capability_exception');
2698         $evidence = external::grade_competency_in_plan($plan->get_id(), $c1->get_id(), 1);
2699     }
2701     /**
2702      * Test update course competency settings.
2703      */
2704     public function test_update_course_competency_settings() {
2705         $this->resetAfterTest(true);
2707         $dg = $this->getDataGenerator();
2709         $course = $dg->create_course();
2710         $roleid = $dg->create_role();
2711         $noobroleid = $dg->create_role();
2712         $context = context_course::instance($course->id);
2713         $compmanager = $this->getDataGenerator()->create_user();
2714         $compnoob = $this->getDataGenerator()->create_user();
2716         assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $roleid, $context->id, true);
2717         assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $roleid, $context->id, true);
2718         assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $noobroleid, $context->id, true);
2720         role_assign($roleid, $compmanager->id, $context->id);
2721         role_assign($noobroleid, $compnoob->id, $context->id);
2722         $dg->enrol_user($compmanager->id, $course->id, $roleid);
2723         $dg->enrol_user($compnoob->id, $course->id, $noobroleid);
2725         $this->setUser($compmanager);
2727         // Start the test.
2728         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2730         $settings = course_competency_settings::get_by_courseid($course->id);
2732         $this->assertTrue((bool)$settings->get_pushratingstouserplans());
2734         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => false));
2736         $settings = course_competency_settings::get_by_courseid($course->id);
2738         $this->assertFalse((bool)$settings->get_pushratingstouserplans());
2739         $this->setUser($compnoob);
2741         $this->setExpectedException('required_capability_exception');
2742         $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2743     }