Merge branch 'MDL-68861-master' of git://github.com/vmdef/moodle
[moodle.git] / competency / tests / api_test.php
blobffe15e344a23a9bc7cfdc9d3db18e8f3359e455b
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.
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 * API tests.
20 * @package core_competency
21 * @copyright 2015 Frédéric Massart - FMCorz.net
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 defined('MOODLE_INTERNAL') || die();
26 global $CFG;
28 use core_competency\api;
29 use core_competency\competency;
30 use core_competency\competency_framework;
31 use core_competency\course_competency_settings;
32 use core_competency\evidence;
33 use core_competency\user_competency;
34 use core_competency\plan;
36 /**
37 * API tests.
39 * @package core_competency
40 * @copyright 2015 Frédéric Massart - FMCorz.net
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 class core_competency_api_testcase extends advanced_testcase {
45 public function test_get_framework_related_contexts() {
46 $this->resetAfterTest(true);
47 $dg = $this->getDataGenerator();
48 $cat1 = $dg->create_category();
49 $cat2 = $dg->create_category(array('parent' => $cat1->id));
50 $cat3 = $dg->create_category(array('parent' => $cat2->id));
51 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
53 $cat1ctx = context_coursecat::instance($cat1->id);
54 $cat2ctx = context_coursecat::instance($cat2->id);
55 $cat3ctx = context_coursecat::instance($cat3->id);
56 $sysctx = context_system::instance();
58 $expected = array($cat1ctx->id => $cat1ctx);
59 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
61 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
62 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
64 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
65 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
68 public function test_get_framework_related_contexts_with_capabilities() {
69 $this->resetAfterTest(true);
70 $dg = $this->getDataGenerator();
71 $user = $dg->create_user();
72 $cat1 = $dg->create_category();
73 $cat2 = $dg->create_category(array('parent' => $cat1->id));
74 $cat3 = $dg->create_category(array('parent' => $cat2->id));
75 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
77 $cat1ctx = context_coursecat::instance($cat1->id);
78 $cat2ctx = context_coursecat::instance($cat2->id);
79 $cat3ctx = context_coursecat::instance($cat3->id);
80 $sysctx = context_system::instance();
82 $roleallow = create_role('Allow', 'allow', 'Allow read');
83 assign_capability('moodle/competency:competencyview', CAP_ALLOW, $roleallow, $sysctx->id);
84 role_assign($roleallow, $user->id, $sysctx->id);
86 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
87 assign_capability('moodle/competency:competencyview', CAP_PROHIBIT, $roleprevent, $sysctx->id);
88 role_assign($roleprevent, $user->id, $cat2ctx->id);
90 accesslib_clear_all_caches_for_unit_testing();
91 $this->setUser($user);
92 $this->assertFalse(has_capability('moodle/competency:competencyview', $cat2ctx));
94 $requiredcap = array('moodle/competency:competencyview');
96 $expected = array();
97 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
99 $expected = array($cat1ctx->id => $cat1ctx);
100 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
102 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
103 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
106 public function test_get_template_related_contexts() {
107 $this->resetAfterTest(true);
108 $dg = $this->getDataGenerator();
109 $cat1 = $dg->create_category();
110 $cat2 = $dg->create_category(array('parent' => $cat1->id));
111 $cat3 = $dg->create_category(array('parent' => $cat2->id));
112 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
114 $cat1ctx = context_coursecat::instance($cat1->id);
115 $cat2ctx = context_coursecat::instance($cat2->id);
116 $cat3ctx = context_coursecat::instance($cat3->id);
117 $sysctx = context_system::instance();
119 $expected = array($cat1ctx->id => $cat1ctx);
120 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
122 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
123 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
125 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
126 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
129 public function test_get_template_related_contexts_with_capabilities() {
130 $this->resetAfterTest(true);
131 $dg = $this->getDataGenerator();
132 $user = $dg->create_user();
133 $cat1 = $dg->create_category();
134 $cat2 = $dg->create_category(array('parent' => $cat1->id));
135 $cat3 = $dg->create_category(array('parent' => $cat2->id));
136 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
138 $cat1ctx = context_coursecat::instance($cat1->id);
139 $cat2ctx = context_coursecat::instance($cat2->id);
140 $cat3ctx = context_coursecat::instance($cat3->id);
141 $sysctx = context_system::instance();
143 $roleallow = create_role('Allow', 'allow', 'Allow read');
144 assign_capability('moodle/competency:templateview', CAP_ALLOW, $roleallow, $sysctx->id);
145 role_assign($roleallow, $user->id, $sysctx->id);
147 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
148 assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $roleprevent, $sysctx->id);
149 role_assign($roleprevent, $user->id, $cat2ctx->id);
151 accesslib_clear_all_caches_for_unit_testing();
152 $this->setUser($user);
153 $this->assertFalse(has_capability('moodle/competency:templateview', $cat2ctx));
155 $requiredcap = array('moodle/competency:templateview');
157 $expected = array();
158 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
160 $expected = array($cat1ctx->id => $cat1ctx);
161 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
163 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
164 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
168 * Test updating a template.
170 * @expectedException coding_exception
172 public function test_update_template() {
173 $cat = $this->getDataGenerator()->create_category();
174 $this->resetAfterTest(true);
175 $this->setAdminUser();
177 $syscontext = context_system::instance();
178 $template = api::create_template((object) array('shortname' => 'testing', 'contextid' => $syscontext->id));
180 $this->assertEquals('testing', $template->get('shortname'));
181 $this->assertEquals($syscontext->id, $template->get('contextid'));
183 // Simple update.
184 api::update_template((object) array('id' => $template->get('id'), 'shortname' => 'success'));
185 $template = api::read_template($template->get('id'));
186 $this->assertEquals('success', $template->get('shortname'));
188 // Trying to change the context.
189 api::update_template((object) array('id' => $template->get('id'), 'contextid' => context_coursecat::instance($cat->id)));
193 * Test listing framework with order param.
195 public function test_list_frameworks() {
196 $this->resetAfterTest(true);
197 $this->setAdminUser();
198 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
200 // Create a list of frameworks.
201 $framework1 = $lpg->create_framework(array(
202 'shortname' => 'shortname_alpha',
203 'idnumber' => 'idnumber_cinnamon',
204 'description' => 'description',
205 'descriptionformat' => FORMAT_HTML,
206 'visible' => true,
207 'contextid' => context_system::instance()->id
210 $framework2 = $lpg->create_framework(array(
211 'shortname' => 'shortname_beetroot',
212 'idnumber' => 'idnumber_apple',
213 'description' => 'description',
214 'descriptionformat' => FORMAT_HTML,
215 'visible' => true,
216 'contextid' => context_system::instance()->id
219 $framework3 = $lpg->create_framework(array(
220 'shortname' => 'shortname_crisps',
221 'idnumber' => 'idnumber_beer',
222 'description' => 'description',
223 'descriptionformat' => FORMAT_HTML,
224 'visible' => false,
225 'contextid' => context_system::instance()->id
228 // Get frameworks list order by shortname desc.
229 $result = api::list_frameworks('shortname', 'DESC', null, 3, context_system::instance());
231 $f = (object) array_shift($result);
232 $this->assertEquals($framework3->get('id'), $f->get('id'));
233 $f = (object) array_shift($result);
234 $this->assertEquals($framework2->get('id'), $f->get('id'));
235 $f = (object) array_shift($result);
236 $this->assertEquals($framework1->get('id'), $f->get('id'));
238 // Get frameworks list order by idnumber asc.
239 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance());
241 $f = (object) array_shift($result);
242 $this->assertEquals($framework2->get('id'), $f->get('id'));
243 $f = (object) array_shift($result);
244 $this->assertEquals($framework3->get('id'), $f->get('id'));
245 $f = (object) array_shift($result);
246 $this->assertEquals($framework1->get('id'), $f->get('id'));
248 // Repeat excluding the non-visible ones.
249 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', true);
250 $this->assertCount(2, $result);
251 $f = (object) array_shift($result);
252 $this->assertEquals($framework2->get('id'), $f->get('id'));
253 $f = (object) array_shift($result);
254 $this->assertEquals($framework1->get('id'), $f->get('id'));
256 // Search by query string, trying match on shortname.
257 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'crisp');
258 $this->assertCount(1, $result);
259 $f = (object) array_shift($result);
260 $this->assertEquals($framework3->get('id'), $f->get('id'));
262 // Search by query string, trying match on shortname, but hidden.
263 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', true, 'crisp');
264 $this->assertCount(0, $result);
266 // Search by query string, trying match on ID number.
267 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'apple');
268 $this->assertCount(1, $result);
269 $f = (object) array_shift($result);
270 $this->assertEquals($framework2->get('id'), $f->get('id'));
272 // Search by query string, trying match on both.
273 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'bee');
274 $this->assertCount(2, $result);
275 $f = (object) array_shift($result);
276 $this->assertEquals($framework2->get('id'), $f->get('id'));
277 $f = (object) array_shift($result);
278 $this->assertEquals($framework3->get('id'), $f->get('id'));
282 * Test duplicate a framework.
284 public function test_duplicate_framework() {
285 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
286 $this->resetAfterTest(true);
287 $this->setAdminUser();
289 $syscontext = context_system::instance();
290 $params = array(
291 'shortname' => 'shortname_a',
292 'idnumber' => 'idnumber_c',
293 'description' => 'description',
294 'descriptionformat' => FORMAT_HTML,
295 'visible' => true,
296 'contextid' => $syscontext->id
298 $framework = $lpg->create_framework($params);
299 $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
300 $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
301 $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
302 $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
303 $competency41 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'),
304 'parentid' => $competency4->get('id'))
306 $competency42 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'),
307 'parentid' => $competency4->get('id'))
309 $competencyidnumbers = array($competency1->get('idnumber'),
310 $competency2->get('idnumber'),
311 $competency3->get('idnumber'),
312 $competency4->get('idnumber'),
313 $competency41->get('idnumber'),
314 $competency42->get('idnumber')
317 $config = json_encode(array(
318 'base' => array('points' => 4),
319 'competencies' => array(
320 array('id' => $competency41->get('id'), 'points' => 3, 'required' => 0),
321 array('id' => $competency42->get('id'), 'points' => 2, 'required' => 1),
324 $competency4->set('ruletype', 'core_competency\competency_rule_points');
325 $competency4->set('ruleoutcome', \core_competency\competency::OUTCOME_EVIDENCE);
326 $competency4->set('ruleconfig', $config);
327 $competency4->update();
329 api::add_related_competency($competency1->get('id'), $competency2->get('id'));
330 api::add_related_competency($competency3->get('id'), $competency4->get('id'));
332 $frameworkduplicated1 = api::duplicate_framework($framework->get('id'));
333 $frameworkduplicated2 = api::duplicate_framework($framework->get('id'));
335 $this->assertEquals($framework->get('idnumber').'_1', $frameworkduplicated1->get('idnumber'));
336 $this->assertEquals($framework->get('idnumber').'_2', $frameworkduplicated2->get('idnumber'));
338 $competenciesfr1 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated1->get('id')));
339 $competenciesfr2 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated2->get('id')));
341 $competencyidsfr1 = array();
342 $competencyidsfr2 = array();
344 foreach ($competenciesfr1 as $cmp) {
345 $competencyidsfr1[] = $cmp->get('idnumber');
347 foreach ($competenciesfr2 as $cmp) {
348 $competencyidsfr2[] = $cmp->get('idnumber');
351 $this->assertEmpty(array_diff($competencyidsfr1, $competencyidnumbers));
352 $this->assertEmpty(array_diff($competencyidsfr2, $competencyidnumbers));
353 $this->assertCount(6, $competenciesfr1);
354 $this->assertCount(6, $competenciesfr2);
356 // Test the related competencies.
357 reset($competenciesfr1);
358 $compduplicated1 = current($competenciesfr1);
359 $relatedcompetencies = $compduplicated1->get_related_competencies();
360 $comprelated = current($relatedcompetencies);
361 $this->assertEquals($comprelated->get('idnumber'), $competency2->get('idnumber'));
363 // Check if config rule have been ported correctly.
364 $competency4duplicated = competency::get_record(array(
365 'idnumber' => $competency4->get('idnumber'),
366 'competencyframeworkid' => $frameworkduplicated2->get('id')
368 $configduplicated = json_decode($competency4duplicated->get('ruleconfig'), true);
369 $configorigin = json_decode($config, true);
370 // Check that the 2 config have the same base.
371 $this->assertEquals($configorigin['base'], $configduplicated['base']);
372 $this->assertEquals(count($configorigin['competencies']), count($configduplicated['competencies']));
373 $competencyidsrules = array();
374 foreach ($configduplicated['competencies'] as $key => $value) {
375 // Check that the only difference between the 2 config is id competency.
376 $this->assertEquals(1, count(array_diff($value, $configorigin['competencies'][$key])));
377 $competencyidsrules[] = $value['id'];
379 $this->assertTrue($competency4duplicated->is_parent_of($competencyidsrules));
381 // Test duplicate an empty framework.
382 $emptyfrm = $lpg->create_framework();
383 $emptyfrmduplicated = api::duplicate_framework($emptyfrm->get('id'));
384 $this->assertEquals($emptyfrm->get('idnumber').'_1', $emptyfrmduplicated->get('idnumber'));
385 $nbcomp = api::count_competencies(array('competencyframeworkid' => $emptyfrmduplicated->get('id')));
386 $this->assertEquals(0, $nbcomp);
391 * Test update plan.
393 public function test_update_plan() {
394 $this->resetAfterTest(true);
395 $dg = $this->getDataGenerator();
396 $usermanageowndraft = $dg->create_user();
397 $usermanageown = $dg->create_user();
398 $usermanagedraft = $dg->create_user();
399 $usermanage = $dg->create_user();
401 $syscontext = context_system::instance();
403 // Creating specific roles.
404 $manageowndraftrole = $dg->create_role(array(
405 'name' => 'User manage own draft',
406 'shortname' => 'manage-own-draft'
408 $manageownrole = $dg->create_role(array(
409 'name' => 'User manage own',
410 'shortname' => 'manage-own'
412 $managedraftrole = $dg->create_role(array(
413 'name' => 'User manage draft',
414 'shortname' => 'manage-draft'
416 $managerole = $dg->create_role(array(
417 'name' => 'User manage',
418 'shortname' => 'manage'
421 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
422 assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
424 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
425 assign_capability('moodle/competency:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
427 assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
428 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
430 assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
431 assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
433 $dg->role_assign($manageowndraftrole, $usermanageowndraft->id, $syscontext->id);
434 $dg->role_assign($manageownrole, $usermanageown->id, $syscontext->id);
435 $dg->role_assign($managedraftrole, $usermanagedraft->id, $syscontext->id);
436 $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
438 // Create first learning plan with user create draft.
439 $this->setUser($usermanageowndraft);
440 $plan = array (
441 'name' => 'plan own draft',
442 'description' => 'plan own draft',
443 'userid' => $usermanageowndraft->id
445 $plan = api::create_plan((object)$plan);
446 $record = $plan->to_record();
447 $record->name = 'plan own draft modified';
449 // Check if user create draft can edit the plan name.
450 $plan = api::update_plan($record);
451 $this->assertInstanceOf('\core_competency\plan', $plan);
453 // The status cannot be changed in this method.
454 $record->status = \core_competency\plan::STATUS_ACTIVE;
455 try {
456 $plan = api::update_plan($record);
457 $this->fail('Updating the status is not allowed.');
458 } catch (coding_exception $e) {
459 $this->assertRegExp('/To change the status of a plan use the appropriate methods./', $e->getMessage());
462 // Test when user with manage own plan capability try to edit other user plan.
463 $record->status = \core_competency\plan::STATUS_DRAFT;
464 $record->name = 'plan create draft modified 2';
465 $this->setUser($usermanageown);
466 try {
467 $plan = api::update_plan($record);
468 $this->fail('User with manage own plan capability can only edit his own plan.');
469 } catch (required_capability_exception $e) {
470 $this->assertTrue(true);
473 // User with manage plan capability cannot edit the other user plans with status draft.
474 $this->setUser($usermanage);
475 $record->name = 'plan create draft modified 3';
476 try {
477 $plan = api::update_plan($record);
478 $this->fail('User with manage plan capability cannot edit the other user plans with status draft');
479 } catch (required_capability_exception $e) {
480 $this->assertTrue(true);
483 // User with manage draft capability can edit other user's learning plan if the status is draft.
484 $this->setUser($usermanagedraft);
485 $record->status = \core_competency\plan::STATUS_DRAFT;
486 $record->name = 'plan manage draft modified 3';
487 $plan = api::update_plan($record);
488 $this->assertInstanceOf('\core_competency\plan', $plan);
490 // User with manage plan capability can create/edit learning plan if status is active/complete.
491 $this->setUser($usermanage);
492 $plan = array (
493 'name' => 'plan create',
494 'description' => 'plan create',
495 'userid' => $usermanage->id,
496 'status' => \core_competency\plan::STATUS_ACTIVE
498 $plan = api::create_plan((object)$plan);
500 // Silently transition to complete status to avoid errors about transitioning to complete.
501 $plan->set('status', \core_competency\plan::STATUS_COMPLETE);
502 $plan->update();
504 $record = $plan->to_record();
505 $record->name = 'plan create own modified';
506 try {
507 api::update_plan($record);
508 $this->fail('Completed plan can not be edited');
509 } catch (coding_exception $e) {
510 $this->assertTrue(true);
515 * @expectedException coding_exception
517 public function test_create_plan_from_template() {
518 $this->resetAfterTest(true);
519 $this->setAdminUser();
521 $u1 = $this->getDataGenerator()->create_user();
522 $tpl = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_template();
524 // Creating a new plan.
525 $plan = api::create_plan_from_template($tpl, $u1->id);
526 $record = $plan->to_record();
527 $this->assertInstanceOf('\core_competency\plan', $plan);
528 $this->assertTrue(\core_competency\plan::record_exists($plan->get('id')));
529 $this->assertEquals($tpl->get('id'), $plan->get('templateid'));
530 $this->assertEquals($u1->id, $plan->get('userid'));
531 $this->assertTrue($plan->is_based_on_template());
533 // Creating a plan that already exists.
534 $plan = api::create_plan_from_template($tpl, $u1->id);
535 $this->assertFalse($plan);
537 // Check that api::create_plan cannot be used.
538 unset($record->id);
539 $plan = api::create_plan($record);
542 public function test_update_plan_based_on_template() {
543 $this->resetAfterTest(true);
544 $dg = $this->getDataGenerator();
545 $lpg = $dg->get_plugin_generator('core_competency');
546 $u1 = $dg->create_user();
547 $u2 = $dg->create_user();
549 $this->setAdminUser();
550 $tpl1 = $lpg->create_template();
551 $tpl2 = $lpg->create_template();
552 $up1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get('id')));
553 $up2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => null));
555 try {
556 // Trying to remove the template dependency.
557 $record = $up1->to_record();
558 $record->templateid = null;
559 api::update_plan($record);
560 $this->fail('A plan cannot be unlinked using api::update_plan()');
561 } catch (coding_exception $e) {
562 // All good.
565 try {
566 // Trying to switch to another template.
567 $record = $up1->to_record();
568 $record->templateid = $tpl2->get('id');
569 api::update_plan($record);
570 $this->fail('A plan cannot be moved to another template.');
571 } catch (coding_exception $e) {
572 // All good.
575 try {
576 // Trying to switch to using a template.
577 $record = $up2->to_record();
578 $record->templateid = $tpl1->get('id');
579 api::update_plan($record);
580 $this->fail('A plan cannot be update to use a template.');
581 } catch (coding_exception $e) {
582 // All good.
586 public function test_unlink_plan_from_template() {
587 $this->resetAfterTest(true);
588 $dg = $this->getDataGenerator();
589 $lpg = $dg->get_plugin_generator('core_competency');
590 $u1 = $dg->create_user();
591 $u2 = $dg->create_user();
593 $this->setAdminUser();
594 $f1 = $lpg->create_framework();
595 $f2 = $lpg->create_framework();
596 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
597 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
598 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
600 $tpl1 = $lpg->create_template();
601 $tpl2 = $lpg->create_template();
603 $tplc1a = $lpg->create_template_competency(array('templateid' => $tpl1->get('id'), 'competencyid' => $c1a->get('id'),
604 'sortorder' => 9));
605 $tplc1b = $lpg->create_template_competency(array('templateid' => $tpl1->get('id'), 'competencyid' => $c1b->get('id'),
606 'sortorder' => 8));
607 $tplc2a = $lpg->create_template_competency(array('templateid' => $tpl2->get('id'), 'competencyid' => $c2a->get('id')));
609 $plan1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get('id'), 'status' => plan::STATUS_ACTIVE));
610 $plan2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => $tpl2->get('id')));
611 $plan3 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get('id'), 'status' => plan::STATUS_COMPLETE));
613 // Check that we have what we expect at this stage.
614 $this->assertEquals(2, \core_competency\template_competency::count_records(array('templateid' => $tpl1->get('id'))));
615 $this->assertEquals(1, \core_competency\template_competency::count_records(array('templateid' => $tpl2->get('id'))));
616 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan1->get('id'))));
617 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan2->get('id'))));
618 $this->assertTrue($plan1->is_based_on_template());
619 $this->assertTrue($plan2->is_based_on_template());
621 // Let's do this!
622 $tpl1comps = \core_competency\template_competency::list_competencies($tpl1->get('id'), true);
623 $tpl2comps = \core_competency\template_competency::list_competencies($tpl2->get('id'), true);
625 api::unlink_plan_from_template($plan1);
627 $plan1->read();
628 $plan2->read();
629 $this->assertCount(2, $tpl1comps);
630 $this->assertCount(1, $tpl2comps);
631 $this->assertEquals(2, \core_competency\template_competency::count_records(array('templateid' => $tpl1->get('id'))));
632 $this->assertEquals(1, \core_competency\template_competency::count_records(array('templateid' => $tpl2->get('id'))));
633 $this->assertEquals(2, \core_competency\plan_competency::count_records(array('planid' => $plan1->get('id'))));
634 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan2->get('id'))));
635 $this->assertFalse($plan1->is_based_on_template());
636 $this->assertEquals($tpl1->get('id'), $plan1->get('origtemplateid'));
637 $this->assertTrue($plan2->is_based_on_template());
638 $this->assertEquals(null, $plan2->get('origtemplateid'));
640 // Check we can unlink draft plan.
641 try {
642 api::unlink_plan_from_template($plan2);
643 } catch (coding_exception $e) {
644 $this->fail('Fail to unlink draft plan.');
647 // Check we can not unlink completed plan.
648 try {
649 api::unlink_plan_from_template($plan3);
650 $this->fail('We can not unlink completed plan.');
651 } catch (coding_exception $e) {
652 // All good.
655 // Even the order remains.
656 $plan1comps = \core_competency\plan_competency::list_competencies($plan1->get('id'));
657 $before = reset($tpl1comps);
658 $after = reset($plan1comps);
659 $this->assertEquals($before->get('id'), $after->get('id'));
660 $this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
661 $before = next($tpl1comps);
662 $after = next($plan1comps);
663 $this->assertEquals($before->get('id'), $after->get('id'));
664 $this->assertEquals($before->get('sortorder'), $after->get('sortorder'));
667 public function test_update_template_updates_plans() {
668 $this->resetAfterTest(true);
669 $this->setAdminUser();
671 $dg = $this->getDataGenerator();
672 $u1 = $dg->create_user();
673 $u2 = $dg->create_user();
674 $lpg = $dg->get_plugin_generator('core_competency');
675 $tpl1 = $lpg->create_template();
676 $tpl2 = $lpg->create_template();
678 // Create plans with data not matching templates.
679 $time = time();
680 $plan1 = $lpg->create_plan(array('templateid' => $tpl1->get('id'), 'userid' => $u1->id,
681 'name' => 'Not good name', 'duedate' => $time + 3600, 'description' => 'Ahah', 'descriptionformat' => FORMAT_MARKDOWN));
682 $plan2 = $lpg->create_plan(array('templateid' => $tpl1->get('id'), 'userid' => $u2->id,
683 'name' => 'Not right name', 'duedate' => $time + 3601, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
684 $plan3 = $lpg->create_plan(array('templateid' => $tpl2->get('id'), 'userid' => $u1->id,
685 'name' => 'Not sweet name', 'duedate' => $time + 3602, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
687 // Prepare our expectations.
688 $plan1->read();
689 $plan2->read();
690 $plan3->read();
692 $this->assertEquals($tpl1->get('id'), $plan1->get('templateid'));
693 $this->assertEquals($tpl1->get('id'), $plan2->get('templateid'));
694 $this->assertEquals($tpl2->get('id'), $plan3->get('templateid'));
695 $this->assertNotEquals($tpl1->get('shortname'), $plan1->get('name'));
696 $this->assertNotEquals($tpl1->get('shortname'), $plan2->get('name'));
697 $this->assertNotEquals($tpl2->get('shortname'), $plan3->get('name'));
698 $this->assertNotEquals($tpl1->get('description'), $plan1->get('description'));
699 $this->assertNotEquals($tpl1->get('description'), $plan2->get('description'));
700 $this->assertNotEquals($tpl2->get('description'), $plan3->get('description'));
701 $this->assertNotEquals($tpl1->get('descriptionformat'), $plan1->get('descriptionformat'));
702 $this->assertNotEquals($tpl1->get('descriptionformat'), $plan2->get('descriptionformat'));
703 $this->assertNotEquals($tpl2->get('descriptionformat'), $plan3->get('descriptionformat'));
704 $this->assertNotEquals($tpl1->get('duedate'), $plan1->get('duedate'));
705 $this->assertNotEquals($tpl1->get('duedate'), $plan2->get('duedate'));
706 $this->assertNotEquals($tpl2->get('duedate'), $plan3->get('duedate'));
708 // Update the template without changing critical fields does not update the plans.
709 $data = $tpl1->to_record();
710 $data->visible = 0;
711 api::update_template($data);
712 $this->assertNotEquals($tpl1->get('shortname'), $plan1->get('name'));
713 $this->assertNotEquals($tpl1->get('shortname'), $plan2->get('name'));
714 $this->assertNotEquals($tpl2->get('shortname'), $plan3->get('name'));
715 $this->assertNotEquals($tpl1->get('description'), $plan1->get('description'));
716 $this->assertNotEquals($tpl1->get('description'), $plan2->get('description'));
717 $this->assertNotEquals($tpl2->get('description'), $plan3->get('description'));
718 $this->assertNotEquals($tpl1->get('descriptionformat'), $plan1->get('descriptionformat'));
719 $this->assertNotEquals($tpl1->get('descriptionformat'), $plan2->get('descriptionformat'));
720 $this->assertNotEquals($tpl2->get('descriptionformat'), $plan3->get('descriptionformat'));
721 $this->assertNotEquals($tpl1->get('duedate'), $plan1->get('duedate'));
722 $this->assertNotEquals($tpl1->get('duedate'), $plan2->get('duedate'));
723 $this->assertNotEquals($tpl2->get('duedate'), $plan3->get('duedate'));
725 // Now really update the template.
726 $data = $tpl1->to_record();
727 $data->shortname = 'Awesome!';
728 $data->description = 'This is too awesome!';
729 $data->descriptionformat = FORMAT_HTML;
730 $data->duedate = $time + 200;
731 api::update_template($data);
732 $tpl1->read();
734 // Now confirm that the right plans were updated.
735 $plan1->read();
736 $plan2->read();
737 $plan3->read();
739 $this->assertEquals($tpl1->get('id'), $plan1->get('templateid'));
740 $this->assertEquals($tpl1->get('id'), $plan2->get('templateid'));
741 $this->assertEquals($tpl2->get('id'), $plan3->get('templateid'));
743 $this->assertEquals($tpl1->get('shortname'), $plan1->get('name'));
744 $this->assertEquals($tpl1->get('shortname'), $plan2->get('name'));
745 $this->assertNotEquals($tpl2->get('shortname'), $plan3->get('name'));
746 $this->assertEquals($tpl1->get('description'), $plan1->get('description'));
747 $this->assertEquals($tpl1->get('description'), $plan2->get('description'));
748 $this->assertNotEquals($tpl2->get('description'), $plan3->get('description'));
749 $this->assertEquals($tpl1->get('descriptionformat'), $plan1->get('descriptionformat'));
750 $this->assertEquals($tpl1->get('descriptionformat'), $plan2->get('descriptionformat'));
751 $this->assertNotEquals($tpl2->get('descriptionformat'), $plan3->get('descriptionformat'));
752 $this->assertEquals($tpl1->get('duedate'), $plan1->get('duedate'));
753 $this->assertEquals($tpl1->get('duedate'), $plan2->get('duedate'));
754 $this->assertNotEquals($tpl2->get('duedate'), $plan3->get('duedate'));
758 * Test that the method to complete a plan.
760 * @expectedException coding_exception
762 public function test_complete_plan() {
763 global $DB;
765 $this->resetAfterTest(true);
766 $this->setAdminUser();
767 $dg = $this->getDataGenerator();
768 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
769 $user = $dg->create_user();
771 // Create a framework and assign competencies.
772 $framework = $lpg->create_framework();
773 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
774 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
775 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
776 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
778 // Create two plans and assign competencies.
779 $plan = $lpg->create_plan(array('userid' => $user->id));
780 $otherplan = $lpg->create_plan(array('userid' => $user->id));
782 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c1->get('id')));
783 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c2->get('id')));
784 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c3->get('id')));
785 $lpg->create_plan_competency(array('planid' => $otherplan->get('id'), 'competencyid' => $c1->get('id')));
787 $uclist = array(
788 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get('id'),
789 'proficiency' => true, 'grade' => 1 )),
790 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get('id'),
791 'proficiency' => false, 'grade' => 2 ))
794 $this->assertEquals(2, \core_competency\user_competency::count_records());
795 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
797 // Change status of the plan to complete.
798 api::complete_plan($plan);
800 // Check that user competencies are now in user_competency_plan objects and still in user_competency.
801 $this->assertEquals(2, \core_competency\user_competency::count_records());
802 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
804 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
806 $this->assertEquals($uclist[0]->get('userid'), $usercompetenciesplan[0]->get('userid'));
807 $this->assertEquals($uclist[0]->get('competencyid'), $usercompetenciesplan[0]->get('competencyid'));
808 $this->assertEquals($uclist[0]->get('proficiency'), (bool) $usercompetenciesplan[0]->get('proficiency'));
809 $this->assertEquals($uclist[0]->get('grade'), $usercompetenciesplan[0]->get('grade'));
810 $this->assertEquals($plan->get('id'), $usercompetenciesplan[0]->get('planid'));
812 $this->assertEquals($uclist[1]->get('userid'), $usercompetenciesplan[1]->get('userid'));
813 $this->assertEquals($uclist[1]->get('competencyid'), $usercompetenciesplan[1]->get('competencyid'));
814 $this->assertEquals($uclist[1]->get('proficiency'), (bool) $usercompetenciesplan[1]->get('proficiency'));
815 $this->assertEquals($uclist[1]->get('grade'), $usercompetenciesplan[1]->get('grade'));
816 $this->assertEquals($plan->get('id'), $usercompetenciesplan[1]->get('planid'));
818 $this->assertEquals($user->id, $usercompetenciesplan[2]->get('userid'));
819 $this->assertEquals($c3->get('id'), $usercompetenciesplan[2]->get('competencyid'));
820 $this->assertNull($usercompetenciesplan[2]->get('proficiency'));
821 $this->assertNull($usercompetenciesplan[2]->get('grade'));
822 $this->assertEquals($plan->get('id'), $usercompetenciesplan[2]->get('planid'));
824 // Check we can not add competency to completed plan.
825 try {
826 api::add_competency_to_plan($plan->get('id'), $c4->get('id'));
827 $this->fail('We can not add competency to completed plan.');
828 } catch (coding_exception $e) {
829 // All good.
832 // Check we can not remove competency to completed plan.
833 try {
834 api::remove_competency_from_plan($plan->get('id'), $c3->get('id'));
835 $this->fail('We can not remove competency to completed plan.');
836 } catch (coding_exception $e) {
837 // All good.
840 // Completing a plan that is completed throws an exception.
841 api::complete_plan($plan);
845 * Set-up the workflow data (review, active, ...).
847 * @return array
849 protected function setup_workflow_data() {
850 $this->resetAfterTest();
852 $dg = $this->getDataGenerator();
853 $user = $dg->create_user();
854 $reviewer = $dg->create_user();
855 $otheruser = $dg->create_user();
857 $syscontext = context_system::instance();
858 $userrole = $dg->create_role();
859 $reviewerrole = $dg->create_role();
860 $otheruserrole = $dg->create_role();
862 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $userrole, $syscontext->id);
863 assign_capability('moodle/competency:planmanage', CAP_ALLOW, $reviewerrole, $syscontext->id);
864 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $reviewerrole, $syscontext->id);
865 $dg->role_assign($userrole, $user->id, $syscontext->id);
866 $dg->role_assign($reviewerrole, $reviewer->id, $syscontext->id);
867 accesslib_clear_all_caches_for_unit_testing();
869 $lpg = $dg->get_plugin_generator('core_competency');
870 $tpl = $lpg->create_template();
871 $plan = $lpg->create_plan(array('userid' => $user->id));
872 $tplplan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tpl->get('id')));
874 return array(
875 'dg' => $dg,
876 'lpg' => $lpg,
877 'user' => $user,
878 'reviewer' => $reviewer,
879 'otheruser' => $otheruser,
880 'plan' => $plan,
881 'tplplan' => $tplplan,
886 * Testing requesting the review of a plan.
888 public function test_plan_request_review() {
889 $data = $this->setup_workflow_data();
890 $dg = $data['dg'];
891 $lpg = $data['lpg'];
892 $user = $data['user'];
893 $reviewer = $data['reviewer'];
894 $otheruser = $data['otheruser'];
895 $plan = $data['plan'];
896 $tplplan = $data['tplplan'];
898 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
899 $this->assertEquals(plan::STATUS_DRAFT, $tplplan->get('status'));
901 // Foreign user cannot do anything.
902 $this->setUser($otheruser);
903 try {
904 api::plan_request_review($plan);
905 $this->fail('The user can not read the plan.');
906 } catch (required_capability_exception $e) {
907 $this->assertEquals('nopermissions', $e->errorcode);
910 // Can not change a plan based on a template.
911 $this->setUser($user);
912 try {
913 api::plan_request_review($tplplan);
914 $this->fail('The plan is based on a template.');
915 } catch (coding_exception $e) {
916 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
919 // Can not send for review when not draft.
920 $this->setUser($user);
921 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
922 try {
923 api::plan_request_review($plan);
924 $this->fail('The plan cannot be sent for review at this stage.');
925 } catch (coding_exception $e) {
926 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
929 // Can not send for review when not draft.
930 $this->setUser($user);
931 $plan->set('status', plan::STATUS_ACTIVE);
932 try {
933 api::plan_request_review($plan);
934 $this->fail('The plan cannot be sent for review at this stage.');
935 } catch (coding_exception $e) {
936 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
939 // Can not send for review when not draft.
940 $this->setUser($user);
941 $plan->set('status', plan::STATUS_IN_REVIEW);
942 try {
943 api::plan_request_review($plan);
944 $this->fail('The plan cannot be sent for review at this stage.');
945 } catch (coding_exception $e) {
946 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
949 // Can not send for review when not draft.
950 $this->setUser($user);
951 $plan->set('status', plan::STATUS_COMPLETE);
952 try {
953 api::plan_request_review($plan);
954 $this->fail('The plan cannot be sent for review at this stage.');
955 } catch (coding_exception $e) {
956 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
959 // Sending for review as a reviewer.
960 $this->setUser($reviewer);
961 $plan->set('status', plan::STATUS_DRAFT);
962 try {
963 api::plan_request_review($plan);
964 $this->fail('The user can not request a review.');
965 } catch (required_capability_exception $e) {
966 $this->assertEquals('nopermissions', $e->errorcode);
969 // Sending for review.
970 $this->setUser($user);
971 api::plan_request_review($plan);
972 $plan->read();
973 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get('status'));
975 // Sending for review by ID.
976 $plan->set('status', plan::STATUS_DRAFT);
977 $plan->update();
978 api::plan_request_review($plan->get('id'));
979 $plan->read();
980 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get('status'));
984 * Testing cancelling the review request.
986 public function test_plan_cancel_review_request() {
987 $data = $this->setup_workflow_data();
988 $dg = $data['dg'];
989 $lpg = $data['lpg'];
990 $user = $data['user'];
991 $reviewer = $data['reviewer'];
992 $otheruser = $data['otheruser'];
993 $plan = $data['plan'];
994 $tplplan = $data['tplplan'];
996 // Set waiting for review.
997 $tplplan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
998 $tplplan->update();
999 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1000 $plan->update();
1002 // Foreign user cannot do anything.
1003 $this->setUser($otheruser);
1004 try {
1005 api::plan_cancel_review_request($plan);
1006 $this->fail('The user can not read the plan.');
1007 } catch (required_capability_exception $e) {
1008 $this->assertEquals('nopermissions', $e->errorcode);
1011 // Can not change a plan based on a template.
1012 $this->setUser($user);
1013 try {
1014 api::plan_cancel_review_request($tplplan);
1015 $this->fail('The plan is based on a template.');
1016 } catch (coding_exception $e) {
1017 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1020 // Can not cancel review request when not waiting for review.
1021 $this->setUser($user);
1022 $plan->set('status', plan::STATUS_DRAFT);
1023 try {
1024 api::plan_cancel_review_request($plan);
1025 $this->fail('The plan cannot be sent for review at this stage.');
1026 } catch (coding_exception $e) {
1027 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1030 // Can not cancel review request when not waiting for review.
1031 $this->setUser($user);
1032 $plan->set('status', plan::STATUS_IN_REVIEW);
1033 try {
1034 api::plan_cancel_review_request($plan);
1035 $this->fail('The plan review cannot be cancelled at this stage.');
1036 } catch (coding_exception $e) {
1037 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1040 // Can not cancel review request when not waiting for review.
1041 $this->setUser($user);
1042 $plan->set('status', plan::STATUS_ACTIVE);
1043 try {
1044 api::plan_cancel_review_request($plan);
1045 $this->fail('The plan review cannot be cancelled at this stage.');
1046 } catch (coding_exception $e) {
1047 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1050 // Can not cancel review request when not waiting for review.
1051 $this->setUser($user);
1052 $plan->set('status', plan::STATUS_COMPLETE);
1053 try {
1054 api::plan_cancel_review_request($plan);
1055 $this->fail('The plan review cannot be cancelled at this stage.');
1056 } catch (coding_exception $e) {
1057 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1060 // Cancelling as a reviewer.
1061 $this->setUser($reviewer);
1062 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1063 try {
1064 api::plan_cancel_review_request($plan);
1065 $this->fail('The user can not cancel a review request.');
1066 } catch (required_capability_exception $e) {
1067 $this->assertEquals('nopermissions', $e->errorcode);
1070 // Cancelling review request.
1071 $this->setUser($user);
1072 api::plan_cancel_review_request($plan);
1073 $plan->read();
1074 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1076 // Cancelling review request by ID.
1077 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1078 $plan->update();
1079 api::plan_cancel_review_request($plan->get('id'));
1080 $plan->read();
1081 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1085 * Testing starting the review.
1087 public function test_plan_start_review() {
1088 $data = $this->setup_workflow_data();
1089 $dg = $data['dg'];
1090 $lpg = $data['lpg'];
1091 $user = $data['user'];
1092 $reviewer = $data['reviewer'];
1093 $otheruser = $data['otheruser'];
1094 $plan = $data['plan'];
1095 $tplplan = $data['tplplan'];
1097 // Set waiting for review.
1098 $tplplan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1099 $tplplan->update();
1100 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1101 $plan->update();
1103 // Foreign user cannot do anything.
1104 $this->setUser($otheruser);
1105 try {
1106 api::plan_start_review($plan);
1107 $this->fail('The user can not read the plan.');
1108 } catch (required_capability_exception $e) {
1109 $this->assertEquals('nopermissions', $e->errorcode);
1112 // Can not change a plan based on a template.
1113 $this->setUser($reviewer);
1114 try {
1115 api::plan_start_review($tplplan);
1116 $this->fail('The plan is based on a template.');
1117 } catch (coding_exception $e) {
1118 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1121 // Can not start a review when not waiting for review.
1122 $this->setUser($reviewer);
1123 $plan->set('status', plan::STATUS_DRAFT);
1124 try {
1125 api::plan_start_review($plan);
1126 $this->fail('The plan review cannot be started at this stage.');
1127 } catch (coding_exception $e) {
1128 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1131 // Can not start a review when not waiting for review.
1132 $this->setUser($reviewer);
1133 $plan->set('status', plan::STATUS_IN_REVIEW);
1134 try {
1135 api::plan_start_review($plan);
1136 $this->fail('The plan review cannot be started at this stage.');
1137 } catch (coding_exception $e) {
1138 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1141 // Can not start a review when not waiting for review.
1142 $this->setUser($reviewer);
1143 $plan->set('status', plan::STATUS_ACTIVE);
1144 try {
1145 api::plan_start_review($plan);
1146 $this->fail('The plan review cannot be started at this stage.');
1147 } catch (coding_exception $e) {
1148 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1151 // Can not start a review when not waiting for review.
1152 $this->setUser($reviewer);
1153 $plan->set('status', plan::STATUS_COMPLETE);
1154 try {
1155 api::plan_start_review($plan);
1156 $this->fail('The plan review cannot be started at this stage.');
1157 } catch (coding_exception $e) {
1158 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1161 // Starting as the owner.
1162 $this->setUser($user);
1163 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1164 try {
1165 api::plan_start_review($plan);
1166 $this->fail('The user can not start a review.');
1167 } catch (required_capability_exception $e) {
1168 $this->assertEquals('nopermissions', $e->errorcode);
1171 // Starting review.
1172 $this->setUser($reviewer);
1173 api::plan_start_review($plan);
1174 $plan->read();
1175 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get('status'));
1176 $this->assertEquals($reviewer->id, $plan->get('reviewerid'));
1178 // Starting review by ID.
1179 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1180 $plan->set('reviewerid', null);
1181 $plan->update();
1182 api::plan_start_review($plan->get('id'));
1183 $plan->read();
1184 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get('status'));
1185 $this->assertEquals($reviewer->id, $plan->get('reviewerid'));
1189 * Testing stopping the review.
1191 public function test_plan_stop_review() {
1192 $data = $this->setup_workflow_data();
1193 $dg = $data['dg'];
1194 $lpg = $data['lpg'];
1195 $user = $data['user'];
1196 $reviewer = $data['reviewer'];
1197 $otheruser = $data['otheruser'];
1198 $plan = $data['plan'];
1199 $tplplan = $data['tplplan'];
1201 // Set waiting for review.
1202 $tplplan->set('status', plan::STATUS_IN_REVIEW);
1203 $tplplan->update();
1204 $plan->set('status', plan::STATUS_IN_REVIEW);
1205 $plan->update();
1207 // Foreign user cannot do anything.
1208 $this->setUser($otheruser);
1209 try {
1210 api::plan_stop_review($plan);
1211 $this->fail('The user can not read the plan.');
1212 } catch (required_capability_exception $e) {
1213 $this->assertEquals('nopermissions', $e->errorcode);
1216 // Can not change a plan based on a template.
1217 $this->setUser($reviewer);
1218 try {
1219 api::plan_stop_review($tplplan);
1220 $this->fail('The plan is based on a template.');
1221 } catch (coding_exception $e) {
1222 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1225 // Can not stop a review whe not in review.
1226 $this->setUser($reviewer);
1227 $plan->set('status', plan::STATUS_DRAFT);
1228 try {
1229 api::plan_stop_review($plan);
1230 $this->fail('The plan review cannot be stopped at this stage.');
1231 } catch (coding_exception $e) {
1232 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1235 // Can not stop a review whe not in review.
1236 $this->setUser($reviewer);
1237 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1238 try {
1239 api::plan_stop_review($plan);
1240 $this->fail('The plan review cannot be stopped at this stage.');
1241 } catch (coding_exception $e) {
1242 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1245 // Can not stop a review whe not in review.
1246 $this->setUser($reviewer);
1247 $plan->set('status', plan::STATUS_ACTIVE);
1248 try {
1249 api::plan_stop_review($plan);
1250 $this->fail('The plan review cannot be stopped at this stage.');
1251 } catch (coding_exception $e) {
1252 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1255 // Can not stop a review whe not in review.
1256 $this->setUser($reviewer);
1257 $plan->set('status', plan::STATUS_COMPLETE);
1258 try {
1259 api::plan_stop_review($plan);
1260 $this->fail('The plan review cannot be stopped at this stage.');
1261 } catch (coding_exception $e) {
1262 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1265 // Stopping as the owner.
1266 $this->setUser($user);
1267 $plan->set('status', plan::STATUS_IN_REVIEW);
1268 try {
1269 api::plan_stop_review($plan);
1270 $this->fail('The user can not stop a review.');
1271 } catch (required_capability_exception $e) {
1272 $this->assertEquals('nopermissions', $e->errorcode);
1275 // Stopping review.
1276 $this->setUser($reviewer);
1277 api::plan_stop_review($plan);
1278 $plan->read();
1279 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1281 // Stopping review by ID.
1282 $plan->set('status', plan::STATUS_IN_REVIEW);
1283 $plan->update();
1284 api::plan_stop_review($plan->get('id'));
1285 $plan->read();
1286 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1290 * Testing approving the plan.
1292 public function test_approve_plan() {
1293 $data = $this->setup_workflow_data();
1294 $dg = $data['dg'];
1295 $lpg = $data['lpg'];
1296 $user = $data['user'];
1297 $reviewer = $data['reviewer'];
1298 $otheruser = $data['otheruser'];
1299 $plan = $data['plan'];
1300 $tplplan = $data['tplplan'];
1302 // Set waiting for review.
1303 $tplplan->set('status', plan::STATUS_IN_REVIEW);
1304 $tplplan->update();
1305 $plan->set('status', plan::STATUS_IN_REVIEW);
1306 $plan->update();
1308 // Foreign user cannot do anything.
1309 $this->setUser($otheruser);
1310 try {
1311 api::approve_plan($plan);
1312 $this->fail('The user can not read the plan.');
1313 } catch (required_capability_exception $e) {
1314 $this->assertEquals('nopermissions', $e->errorcode);
1317 // Can not change a plan based on a template.
1318 $this->setUser($reviewer);
1319 try {
1320 api::approve_plan($tplplan);
1321 $this->fail('The plan is based on a template.');
1322 } catch (coding_exception $e) {
1323 $this->assertRegExp('/Template plans are already approved./', $e->getMessage());
1326 // Can not approve a plan already approved.
1327 $this->setUser($reviewer);
1328 $plan->set('status', plan::STATUS_ACTIVE);
1329 try {
1330 api::approve_plan($plan);
1331 $this->fail('The plan cannot be approved at this stage.');
1332 } catch (coding_exception $e) {
1333 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1336 // Can not approve a plan already approved.
1337 $this->setUser($reviewer);
1338 $plan->set('status', plan::STATUS_COMPLETE);
1339 try {
1340 api::approve_plan($plan);
1341 $this->fail('The plan cannot be approved at this stage.');
1342 } catch (coding_exception $e) {
1343 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1346 // Approve as the owner.
1347 $this->setUser($user);
1348 $plan->set('status', plan::STATUS_IN_REVIEW);
1349 try {
1350 api::approve_plan($plan);
1351 $this->fail('The user can not approve the plan.');
1352 } catch (required_capability_exception $e) {
1353 $this->assertEquals('nopermissions', $e->errorcode);
1356 // Approve plan from in review.
1357 $this->setUser($reviewer);
1358 api::approve_plan($plan);
1359 $plan->read();
1360 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get('status'));
1362 // Approve plan by ID.
1363 $plan->set('status', plan::STATUS_IN_REVIEW);
1364 $plan->update();
1365 api::approve_plan($plan->get('id'));
1366 $plan->read();
1367 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get('status'));
1369 // Approve plan from draft.
1370 $plan->set('status', plan::STATUS_DRAFT);
1371 $plan->update();
1372 api::approve_plan($plan);
1373 $plan->read();
1374 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get('status'));
1376 // Approve plan from waiting for review.
1377 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1378 $plan->update();
1379 api::approve_plan($plan);
1380 $plan->read();
1381 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get('status'));
1385 * Testing stopping the review.
1387 public function test_unapprove_plan() {
1388 $data = $this->setup_workflow_data();
1389 $dg = $data['dg'];
1390 $lpg = $data['lpg'];
1391 $user = $data['user'];
1392 $reviewer = $data['reviewer'];
1393 $otheruser = $data['otheruser'];
1394 $plan = $data['plan'];
1395 $tplplan = $data['tplplan'];
1397 // Set waiting for review.
1398 $tplplan->set('status', plan::STATUS_ACTIVE);
1399 $tplplan->update();
1400 $plan->set('status', plan::STATUS_ACTIVE);
1401 $plan->update();
1403 // Foreign user cannot do anything.
1404 $this->setUser($otheruser);
1405 try {
1406 api::unapprove_plan($plan);
1407 $this->fail('The user can not read the plan.');
1408 } catch (required_capability_exception $e) {
1409 $this->assertEquals('nopermissions', $e->errorcode);
1412 // Can not change a plan based on a template.
1413 $this->setUser($reviewer);
1414 try {
1415 api::unapprove_plan($tplplan);
1416 $this->fail('The plan is based on a template.');
1417 } catch (coding_exception $e) {
1418 $this->assertRegExp('/Template plans are always approved./', $e->getMessage());
1421 // Can not unapprove a non-draft plan.
1422 $this->setUser($reviewer);
1423 $plan->set('status', plan::STATUS_DRAFT);
1424 try {
1425 api::unapprove_plan($plan);
1426 $this->fail('The plan cannot be sent back to draft at this stage.');
1427 } catch (coding_exception $e) {
1428 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1431 // Can not unapprove a non-draft plan.
1432 $this->setUser($reviewer);
1433 $plan->set('status', plan::STATUS_WAITING_FOR_REVIEW);
1434 try {
1435 api::unapprove_plan($plan);
1436 $this->fail('The plan cannot be sent back to draft at this stage.');
1437 } catch (coding_exception $e) {
1438 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1441 // Can not unapprove a non-draft plan.
1442 $this->setUser($reviewer);
1443 $plan->set('status', plan::STATUS_IN_REVIEW);
1444 try {
1445 api::unapprove_plan($plan);
1446 $this->fail('The plan cannot be sent back to draft at this stage.');
1447 } catch (coding_exception $e) {
1448 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1451 // Can not unapprove a non-draft plan.
1452 $this->setUser($reviewer);
1453 $plan->set('status', plan::STATUS_COMPLETE);
1454 try {
1455 api::unapprove_plan($plan);
1456 $this->fail('The plan cannot be sent back to draft at this stage.');
1457 } catch (coding_exception $e) {
1458 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1461 // Unapprove as the owner.
1462 $this->setUser($user);
1463 $plan->set('status', plan::STATUS_ACTIVE);
1464 try {
1465 api::unapprove_plan($plan);
1466 $this->fail('The user can not unapprove the plan.');
1467 } catch (required_capability_exception $e) {
1468 $this->assertEquals('nopermissions', $e->errorcode);
1471 // Unapprove plan.
1472 $this->setUser($reviewer);
1473 api::unapprove_plan($plan);
1474 $plan->read();
1475 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1477 // Unapprove plan by ID.
1478 $plan->set('status', plan::STATUS_ACTIVE);
1479 $plan->update();
1480 api::unapprove_plan($plan->get('id'));
1481 $plan->read();
1482 $this->assertEquals(plan::STATUS_DRAFT, $plan->get('status'));
1486 * Test update plan and the managing of archived user competencies.
1488 public function test_update_plan_manage_archived_competencies() {
1489 global $DB;
1491 $this->resetAfterTest(true);
1492 $dg = $this->getDataGenerator();
1493 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1495 $syscontext = context_system::instance();
1497 // Create users and roles for the test.
1498 $user = $dg->create_user();
1499 $manageownrole = $dg->create_role(array(
1500 'name' => 'User manage own',
1501 'shortname' => 'manageown'
1503 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1504 assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1505 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
1506 assign_capability('moodle/competency:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
1507 $dg->role_assign($manageownrole, $user->id, $syscontext->id);
1508 $this->setUser($user);
1510 // Create a framework and assign competencies.
1511 $framework = $lpg->create_framework();
1512 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1513 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1514 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1516 // Create two plans and assign competencies.
1517 $plan = $lpg->create_plan(array('userid' => $user->id));
1518 $otherplan = $lpg->create_plan(array('userid' => $user->id));
1520 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c1->get('id')));
1521 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c2->get('id')));
1522 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c3->get('id')));
1523 $lpg->create_plan_competency(array('planid' => $otherplan->get('id'), 'competencyid' => $c1->get('id')));
1525 $uclist = array(
1526 $lpg->create_user_competency(array(
1527 'userid' => $user->id,
1528 'competencyid' => $c1->get('id'),
1529 'proficiency' => true,
1530 'grade' => 1
1532 $lpg->create_user_competency(array(
1533 'userid' => $user->id,
1534 'competencyid' => $c2->get('id'),
1535 'proficiency' => false,
1536 'grade' => 2
1540 // Change status of the plan to complete.
1541 $record = $plan->to_record();
1542 $record->status = \core_competency\plan::STATUS_COMPLETE;
1544 try {
1545 $plan = api::update_plan($record);
1546 $this->fail('We cannot complete a plan using api::update_plan().');
1547 } catch (coding_exception $e) {
1548 // All good.
1550 api::complete_plan($plan);
1552 // Check that user compretencies are now in user_competency_plan objects and still in user_competency.
1553 $this->assertEquals(2, \core_competency\user_competency::count_records());
1554 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
1556 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
1558 $this->assertEquals($uclist[0]->get('userid'), $usercompetenciesplan[0]->get('userid'));
1559 $this->assertEquals($uclist[0]->get('competencyid'), $usercompetenciesplan[0]->get('competencyid'));
1560 $this->assertEquals($uclist[0]->get('proficiency'), (bool) $usercompetenciesplan[0]->get('proficiency'));
1561 $this->assertEquals($uclist[0]->get('grade'), $usercompetenciesplan[0]->get('grade'));
1562 $this->assertEquals($plan->get('id'), $usercompetenciesplan[0]->get('planid'));
1564 $this->assertEquals($uclist[1]->get('userid'), $usercompetenciesplan[1]->get('userid'));
1565 $this->assertEquals($uclist[1]->get('competencyid'), $usercompetenciesplan[1]->get('competencyid'));
1566 $this->assertEquals($uclist[1]->get('proficiency'), (bool) $usercompetenciesplan[1]->get('proficiency'));
1567 $this->assertEquals($uclist[1]->get('grade'), $usercompetenciesplan[1]->get('grade'));
1568 $this->assertEquals($plan->get('id'), $usercompetenciesplan[1]->get('planid'));
1570 $this->assertEquals($user->id, $usercompetenciesplan[2]->get('userid'));
1571 $this->assertEquals($c3->get('id'), $usercompetenciesplan[2]->get('competencyid'));
1572 $this->assertNull($usercompetenciesplan[2]->get('proficiency'));
1573 $this->assertNull($usercompetenciesplan[2]->get('grade'));
1574 $this->assertEquals($plan->get('id'), $usercompetenciesplan[2]->get('planid'));
1576 // Change status of the plan to active.
1577 $record = $plan->to_record();
1578 $record->status = \core_competency\plan::STATUS_ACTIVE;
1580 try {
1581 api::update_plan($record);
1582 $this->fail('Completed plan can not be edited');
1583 } catch (coding_exception $e) {
1584 // All good.
1587 api::reopen_plan($record->id);
1588 // Check that user_competency_plan objects are deleted if the plan status is changed to another status.
1589 $this->assertEquals(2, \core_competency\user_competency::count_records());
1590 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
1594 * Test completing plan does not change the order of competencies.
1596 public function test_complete_plan_doesnot_change_order() {
1597 global $DB;
1599 $this->resetAfterTest(true);
1600 $this->setAdminUser();
1601 $dg = $this->getDataGenerator();
1602 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1604 $syscontext = context_system::instance();
1606 // Create users and roles for the test.
1607 $user = $dg->create_user();
1609 // Create a framework and assign competencies.
1610 $framework = $lpg->create_framework();
1611 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1612 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1613 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1615 // Create two plans and assign competencies.
1616 $plan = $lpg->create_plan(array('userid' => $user->id));
1618 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c1->get('id')));
1619 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c2->get('id')));
1620 $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c3->get('id')));
1622 // Changing competencies order in plan competency.
1623 api::reorder_plan_competency($plan->get('id'), $c1->get('id'), $c3->get('id'));
1625 $competencies = api::list_plan_competencies($plan);
1626 $this->assertEquals($c2->get('id'), $competencies[0]->competency->get('id'));
1627 $this->assertEquals($c3->get('id'), $competencies[1]->competency->get('id'));
1628 $this->assertEquals($c1->get('id'), $competencies[2]->competency->get('id'));
1630 // Completing plan.
1631 api::complete_plan($plan);
1633 $competencies = api::list_plan_competencies($plan);
1635 // Completing plan does not change order.
1636 $this->assertEquals($c2->get('id'), $competencies[0]->competency->get('id'));
1637 $this->assertEquals($c3->get('id'), $competencies[1]->competency->get('id'));
1638 $this->assertEquals($c1->get('id'), $competencies[2]->competency->get('id'));
1640 // Testing plan based on template.
1641 $template = $lpg->create_template();
1642 $framework = $lpg->create_framework();
1643 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1644 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1645 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1647 $lpg->create_template_competency(array(
1648 'templateid' => $template->get('id'),
1649 'competencyid' => $c1->get('id')
1651 $lpg->create_template_competency(array(
1652 'templateid' => $template->get('id'),
1653 'competencyid' => $c2->get('id')
1655 $lpg->create_template_competency(array(
1656 'templateid' => $template->get('id'),
1657 'competencyid' => $c3->get('id')
1659 // Reorder competencies in template.
1660 api::reorder_template_competency($template->get('id'), $c1->get('id'), $c3->get('id'));
1662 // Create plan from template.
1663 $plan = api::create_plan_from_template($template->get('id'), $user->id);
1665 $competencies = api::list_plan_competencies($plan);
1667 // Completing plan does not change order.
1668 $this->assertEquals($c2->get('id'), $competencies[0]->competency->get('id'));
1669 $this->assertEquals($c3->get('id'), $competencies[1]->competency->get('id'));
1670 $this->assertEquals($c1->get('id'), $competencies[2]->competency->get('id'));
1672 // Completing plan.
1673 api::complete_plan($plan);
1675 $competencies = api::list_plan_competencies($plan);
1677 // Completing plan does not change order.
1678 $this->assertEquals($c2->get('id'), $competencies[0]->competency->get('id'));
1679 $this->assertEquals($c3->get('id'), $competencies[1]->competency->get('id'));
1680 $this->assertEquals($c1->get('id'), $competencies[2]->competency->get('id'));
1684 * Test remove plan and the managing of archived user competencies.
1686 public function test_delete_plan_manage_archived_competencies() {
1687 $this->resetAfterTest(true);
1688 $dg = $this->getDataGenerator();
1689 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1691 $syscontext = context_system::instance();
1693 // Create user and role for the test.
1694 $user = $dg->create_user();
1695 $managerole = $dg->create_role(array(
1696 'name' => 'User manage own',
1697 'shortname' => 'manageown'
1699 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $managerole, $syscontext->id);
1700 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $managerole, $syscontext->id);
1701 $dg->role_assign($managerole, $user->id, $syscontext->id);
1702 $this->setUser($user);
1704 // Create a framework and assign competencies.
1705 $framework = $lpg->create_framework();
1706 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1707 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1708 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1710 // Create completed plan with records in user_competency.
1711 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
1713 $lpg->create_plan_competency(array('planid' => $completedplan->get('id'), 'competencyid' => $c1->get('id')));
1714 $lpg->create_plan_competency(array('planid' => $completedplan->get('id'), 'competencyid' => $c2->get('id')));
1716 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get('id')));
1717 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get('id')));
1719 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get('id'),
1720 'planid' => $completedplan->get('id')));
1721 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get('id'),
1722 'planid' => $completedplan->get('id')));
1724 api::delete_plan($completedplan->get('id'));
1726 // Check that achived user competencies are deleted.
1727 $this->assertEquals(0, \core_competency\plan::count_records());
1728 $this->assertEquals(2, \core_competency\user_competency::count_records());
1729 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
1733 * Test listing of plan competencies.
1735 public function test_list_plan_competencies_manage_archived_competencies() {
1736 $this->resetAfterTest(true);
1737 $dg = $this->getDataGenerator();
1738 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1740 $syscontext = context_system::instance();
1742 // Create user and role for the test.
1743 $user = $dg->create_user();
1744 $viewrole = $dg->create_role(array(
1745 'name' => 'User view',
1746 'shortname' => 'view'
1748 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $viewrole, $syscontext->id);
1749 assign_capability('moodle/competency:planview', CAP_ALLOW, $viewrole, $syscontext->id);
1750 $dg->role_assign($viewrole, $user->id, $syscontext->id);
1751 $this->setUser($user);
1753 // Create a framework and assign competencies.
1754 $framework = $lpg->create_framework();
1755 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1756 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1757 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1759 // Create draft plan with records in user_competency.
1760 $draftplan = $lpg->create_plan(array('userid' => $user->id));
1762 $lpg->create_plan_competency(array('planid' => $draftplan->get('id'), 'competencyid' => $c1->get('id')));
1763 $lpg->create_plan_competency(array('planid' => $draftplan->get('id'), 'competencyid' => $c2->get('id')));
1764 $lpg->create_plan_competency(array('planid' => $draftplan->get('id'), 'competencyid' => $c3->get('id')));
1766 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get('id')));
1767 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get('id')));
1769 // Check that user_competency objects are returned when plan status is not complete.
1770 $plancompetencies = api::list_plan_competencies($draftplan);
1772 $this->assertCount(3, $plancompetencies);
1773 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[0]->usercompetency);
1774 $this->assertEquals($uc1->get('id'), $plancompetencies[0]->usercompetency->get('id'));
1775 $this->assertNull($plancompetencies[0]->usercompetencyplan);
1777 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[1]->usercompetency);
1778 $this->assertEquals($uc2->get('id'), $plancompetencies[1]->usercompetency->get('id'));
1779 $this->assertNull($plancompetencies[1]->usercompetencyplan);
1781 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[2]->usercompetency);
1782 $this->assertEquals(0, $plancompetencies[2]->usercompetency->get('id'));
1783 $this->assertNull($plancompetencies[2]->usercompetencyplan);
1785 // Create completed plan with records in user_competency_plan.
1786 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
1788 $pc1 = $lpg->create_plan_competency(array('planid' => $completedplan->get('id'), 'competencyid' => $c1->get('id')));
1789 $pc2 = $lpg->create_plan_competency(array('planid' => $completedplan->get('id'), 'competencyid' => $c2->get('id')));
1790 $pc3 = $lpg->create_plan_competency(array('planid' => $completedplan->get('id'), 'competencyid' => $c3->get('id')));
1792 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get('id'),
1793 'planid' => $completedplan->get('id')));
1794 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get('id'),
1795 'planid' => $completedplan->get('id')));
1796 $ucp3 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c3->get('id'),
1797 'planid' => $completedplan->get('id')));
1799 // Check that user_competency_plan objects are returned when plan status is complete.
1800 $plancompetencies = api::list_plan_competencies($completedplan);
1802 $this->assertCount(3, $plancompetencies);
1803 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[0]->usercompetencyplan);
1804 $this->assertEquals($ucp1->get('id'), $plancompetencies[0]->usercompetencyplan->get('id'));
1805 $this->assertNull($plancompetencies[0]->usercompetency);
1806 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[1]->usercompetencyplan);
1807 $this->assertEquals($ucp2->get('id'), $plancompetencies[1]->usercompetencyplan->get('id'));
1808 $this->assertNull($plancompetencies[1]->usercompetency);
1809 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[2]->usercompetencyplan);
1810 $this->assertEquals($ucp3->get('id'), $plancompetencies[2]->usercompetencyplan->get('id'));
1811 $this->assertNull($plancompetencies[2]->usercompetency);
1814 public function test_create_template_cohort() {
1815 $this->resetAfterTest(true);
1816 $this->setAdminUser();
1818 $dg = $this->getDataGenerator();
1819 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1821 $c1 = $dg->create_cohort();
1822 $c2 = $dg->create_cohort();
1823 $t1 = $lpg->create_template();
1824 $t2 = $lpg->create_template();
1826 $this->assertEquals(0, \core_competency\template_cohort::count_records());
1828 // Create two relations with mixed parameters.
1829 $result = api::create_template_cohort($t1->get('id'), $c1->id);
1830 $result = api::create_template_cohort($t1, $c2);
1832 $this->assertEquals(2, \core_competency\template_cohort::count_records());
1833 $this->assertInstanceOf('core_competency\template_cohort', $result);
1834 $this->assertEquals($c2->id, $result->get('cohortid'));
1835 $this->assertEquals($t1->get('id'), $result->get('templateid'));
1836 $this->assertEquals(2, \core_competency\template_cohort::count_records_select('templateid = :id',
1837 array('id' => $t1->get('id'))));
1838 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id',
1839 array('id' => $t2->get('id'))));
1842 public function test_create_template_cohort_permissions() {
1843 $this->resetAfterTest(true);
1845 $dg = $this->getDataGenerator();
1846 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1847 $cat = $dg->create_category();
1848 $catcontext = context_coursecat::instance($cat->id);
1849 $syscontext = context_system::instance();
1851 $user = $dg->create_user();
1852 $role = $dg->create_role();
1853 assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $syscontext->id, true);
1854 $dg->role_assign($role, $user->id, $syscontext->id);
1856 $cohortrole = $dg->create_role();
1857 assign_capability('moodle/cohort:view', CAP_ALLOW, $cohortrole, $syscontext->id, true);
1859 accesslib_clear_all_caches_for_unit_testing();
1861 $c1 = $dg->create_cohort();
1862 $c2 = $dg->create_cohort(array('visible' => 0, 'contextid' => $catcontext->id));
1863 $t1 = $lpg->create_template();
1865 $this->assertEquals(0, \core_competency\template_cohort::count_records());
1867 $this->setUser($user);
1868 $result = api::create_template_cohort($t1, $c1);
1869 $this->assertInstanceOf('core_competency\\template_cohort', $result);
1871 try {
1872 $result = api::create_template_cohort($t1, $c2);
1873 $this->fail('Permission required.');
1874 } catch (required_capability_exception $e) {
1875 // That's what should happen.
1878 // Try again with the right permissions.
1879 $dg->role_assign($cohortrole, $user->id, $catcontext->id);
1880 accesslib_clear_all_caches_for_unit_testing();
1882 $result = api::create_template_cohort($t1, $c2);
1883 $this->assertInstanceOf('core_competency\\template_cohort', $result);
1886 public function test_reorder_template_competencies_permissions() {
1887 $this->resetAfterTest(true);
1889 $dg = $this->getDataGenerator();
1890 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1891 $cat = $dg->create_category();
1892 $catcontext = context_coursecat::instance($cat->id);
1893 $syscontext = context_system::instance();
1895 $user = $dg->create_user();
1896 $role = $dg->create_role();
1897 assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $syscontext->id, true);
1898 $dg->role_assign($role, $user->id, $syscontext->id);
1900 // Create a template.
1901 $template = $lpg->create_template(array('contextid' => $catcontext->id));
1903 // Create a competency framework.
1904 $framework = $lpg->create_framework(array('contextid' => $catcontext->id));
1906 // Create competencies.
1907 $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1908 $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1910 // Add the competencies.
1911 $lpg->create_template_competency(array(
1912 'templateid' => $template->get('id'),
1913 'competencyid' => $competency1->get('id')
1915 $lpg->create_template_competency(array(
1916 'templateid' => $template->get('id'),
1917 'competencyid' => $competency2->get('id')
1919 $this->setUser($user);
1920 // Can reorder competencies with system context permissions in category context.
1921 $result = api::reorder_template_competency($template->get('id'), $competency2->get('id'), $competency1->get('id'));
1922 $this->assertTrue($result);
1923 unassign_capability('moodle/competency:templatemanage', $role, $syscontext->id);
1924 accesslib_clear_all_caches_for_unit_testing();
1926 try {
1927 api::reorder_template_competency($template->get('id'), $competency2->get('id'), $competency1->get('id'));
1928 $this->fail('Exception expected due to not permissions to manage template competencies');
1929 } catch (required_capability_exception $e) {
1930 $this->assertEquals('nopermissions', $e->errorcode);
1933 // Giving permissions in category context.
1934 assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $catcontext->id, true);
1935 $dg->role_assign($role, $user->id, $catcontext->id);
1936 // User with templatemanage capability in category context can reorder competencies in temple.
1937 $result = api::reorder_template_competency($template->get('id'), $competency1->get('id'), $competency2->get('id'));
1938 $this->assertTrue($result);
1939 // Removing templatemanage capability in category context.
1940 unassign_capability('moodle/competency:templatemanage', $role, $catcontext->id);
1941 accesslib_clear_all_caches_for_unit_testing();
1943 try {
1944 api::reorder_template_competency($template->get('id'), $competency2->get('id'), $competency1->get('id'));
1945 $this->fail('Exception expected due to not permissions to manage template competencies');
1946 } catch (required_capability_exception $e) {
1947 $this->assertEquals('nopermissions', $e->errorcode);
1951 public function test_delete_template() {
1952 $this->resetAfterTest(true);
1953 $this->setAdminUser();
1955 $dg = $this->getDataGenerator();
1956 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1958 $c1 = $dg->create_cohort();
1959 $c2 = $dg->create_cohort();
1960 $template = $lpg->create_template();
1961 $id = $template->get('id');
1963 // Create 2 template cohorts.
1964 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get('id'), 'cohortid' => $c1->id));
1965 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get('id'), 'cohortid' => $c2->id));
1967 // Check pre-test.
1968 $this->assertTrue(\core_competency\template::record_exists($id));
1969 $this->assertEquals(2, \core_competency\template_cohort::count_records(array('templateid' => $id)));
1971 $result = api::delete_template($template->get('id'));
1972 $this->assertTrue($result);
1974 // Check that the template deos not exist anymore.
1975 $this->assertFalse(\core_competency\template::record_exists($id));
1977 // Test if associated cohorts are also deleted.
1978 $this->assertEquals(0, \core_competency\template_cohort::count_records(array('templateid' => $id)));
1981 public function test_delete_template_cohort() {
1982 $this->resetAfterTest(true);
1983 $this->setAdminUser();
1985 $dg = $this->getDataGenerator();
1986 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1988 $c1 = $dg->create_cohort();
1989 $c2 = $dg->create_cohort();
1990 $t1 = $lpg->create_template();
1991 $t2 = $lpg->create_template();
1992 $tc1 = $lpg->create_template_cohort(array('templateid' => $t1->get('id'), 'cohortid' => $c1->id));
1993 $tc1 = $lpg->create_template_cohort(array('templateid' => $t2->get('id'), 'cohortid' => $c2->id));
1995 $this->assertEquals(2, \core_competency\template_cohort::count_records());
1996 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id',
1997 array('id' => $t1->get('id'))));
1998 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id',
1999 array('id' => $t2->get('id'))));
2001 // Delete existing.
2002 $result = api::delete_template_cohort($t1->get('id'), $c1->id);
2003 $this->assertTrue($result);
2004 $this->assertEquals(1, \core_competency\template_cohort::count_records());
2005 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id',
2006 array('id' => $t1->get('id'))));
2007 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id',
2008 array('id' => $t2->get('id'))));
2010 // Delete non-existant.
2011 $result = api::delete_template_cohort($t1->get('id'), $c1->id);
2012 $this->assertTrue($result);
2013 $this->assertEquals(1, \core_competency\template_cohort::count_records());
2014 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id',
2015 array('id' => $t1->get('id'))));
2016 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id',
2017 array('id' => $t2->get('id'))));
2020 public function test_add_evidence_log() {
2021 $this->resetAfterTest(true);
2022 $dg = $this->getDataGenerator();
2023 $lpg = $dg->get_plugin_generator('core_competency');
2025 $u1 = $dg->create_user();
2026 $u1ctx = context_user::instance($u1->id);
2027 $f1 = $lpg->create_framework();
2028 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2029 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2031 // Creating a standard evidence with minimal information.
2032 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG,
2033 'invaliddata', 'error');
2034 $evidence->read();
2035 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2036 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2037 $this->assertSame(null, $uc->get('grade'));
2038 $this->assertSame(null, $uc->get('proficiency'));
2039 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2040 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2041 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get('action'));
2042 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2043 $this->assertEquals('error', $evidence->get('desccomponent'));
2044 $this->assertSame(null, $evidence->get('desca'));
2045 $this->assertSame(null, $evidence->get('url'));
2046 $this->assertSame(null, $evidence->get('grade'));
2047 $this->assertSame(null, $evidence->get('actionuserid'));
2049 // Creating a standard evidence with more information.
2050 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2051 'error', '$a', false, 'http://moodle.org', null, 2, 'The evidence of prior learning were reviewed.');
2052 $evidence->read();
2053 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2054 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2055 $this->assertSame(null, $uc->get('grade'));
2056 $this->assertSame(null, $uc->get('proficiency'));
2057 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2058 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2059 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get('action'));
2060 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2061 $this->assertEquals('error', $evidence->get('desccomponent'));
2062 $this->assertEquals('$a', $evidence->get('desca'));
2063 $this->assertEquals('http://moodle.org', $evidence->get('url'));
2064 $this->assertSame(null, $evidence->get('grade'));
2065 $this->assertEquals(2, $evidence->get('actionuserid'));
2066 $this->assertSame('The evidence of prior learning were reviewed.', $evidence->get('note'));
2068 // Creating a standard evidence and send for review.
2069 $evidence = api::add_evidence($u1->id, $c2->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2070 'error', null, true);
2071 $evidence->read();
2072 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get('id')));
2073 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get('status'));
2075 // Trying to pass a grade should fail.
2076 try {
2077 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2078 'error', null, false, null, 1);
2079 $this->fail('A grade can not be set');
2080 } catch (coding_exception $e) {
2081 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2085 public function test_add_evidence_complete() {
2086 $this->resetAfterTest(true);
2087 $dg = $this->getDataGenerator();
2088 $lpg = $dg->get_plugin_generator('core_competency');
2090 $u1 = $dg->create_user();
2091 $u1ctx = context_user::instance($u1->id);
2092 $scale = $dg->create_scale(array('scale' => 'A,B,C,D'));
2093 $scaleconfig = array(array('scaleid' => $scale->id));
2094 $scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 1, 'proficient' => 0);
2095 $scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 1);
2096 $scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 0, 'proficient' => 1);
2097 $c2scaleconfig = array(array('scaleid' => $scale->id));
2098 $c2scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 0, 'proficient' => 1);
2099 $c2scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 0);
2100 $c2scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 1, 'proficient' => 1);
2101 $f1 = $lpg->create_framework(array('scaleid' => $scale->id, 'scaleconfiguration' => $scaleconfig));
2102 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2103 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'scaleid' => $scale->id,
2104 'scaleconfiguration' => $c2scaleconfig));
2105 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2107 // Creating an evidence with minimal information.
2108 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2109 'error');
2110 $evidence->read();
2111 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2112 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2113 $this->assertEquals(2, $uc->get('grade')); // The grade has been set automatically to the framework default.
2114 $this->assertEquals(0, $uc->get('proficiency'));
2115 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2116 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2117 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get('action'));
2118 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2119 $this->assertEquals('error', $evidence->get('desccomponent'));
2120 $this->assertSame(null, $evidence->get('desca'));
2121 $this->assertSame(null, $evidence->get('url'));
2122 $this->assertEquals(2, $evidence->get('grade'));
2123 $this->assertSame(null, $evidence->get('actionuserid'));
2125 // Creating an evidence complete on competency with custom scale.
2126 $evidence = api::add_evidence($u1->id, $c2->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2127 'error');
2128 $evidence->read();
2129 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get('id')));
2130 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2131 $this->assertEquals(4, $uc->get('grade')); // The grade has been set automatically to the competency default.
2132 $this->assertEquals(true, $uc->get('proficiency'));
2133 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2134 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2135 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get('action'));
2136 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2137 $this->assertEquals('error', $evidence->get('desccomponent'));
2138 $this->assertSame(null, $evidence->get('desca'));
2139 $this->assertSame(null, $evidence->get('url'));
2140 $this->assertEquals(4, $evidence->get('grade'));
2141 $this->assertSame(null, $evidence->get('actionuserid'));
2143 // Creating an evidence complete on a user competency with an existing grade.
2144 $uc = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c3->get('id'), 'grade' => 1,
2145 'proficiency' => 0));
2146 $this->assertEquals(1, $uc->get('grade'));
2147 $this->assertEquals(0, $uc->get('proficiency'));
2148 $evidence = api::add_evidence($u1->id, $c3->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2149 'error');
2150 $evidence->read();
2151 $uc->read();
2152 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2153 $this->assertEquals(1, $uc->get('grade')); // The grade has not been changed.
2154 $this->assertEquals(0, $uc->get('proficiency'));
2155 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2156 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2157 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get('action'));
2158 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2159 $this->assertEquals('error', $evidence->get('desccomponent'));
2160 $this->assertSame(null, $evidence->get('desca'));
2161 $this->assertSame(null, $evidence->get('url'));
2162 $this->assertEquals(2, $evidence->get('grade')); // The complete grade has been set.
2163 $this->assertSame(null, $evidence->get('actionuserid'));
2165 // Creating a standard evidence and send for review.
2166 $evidence = api::add_evidence($u1->id, $c2->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2167 'error', null, true);
2168 $evidence->read();
2169 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get('id')));
2170 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get('status'));
2172 // Trying to pass a grade should throw an exception.
2173 try {
2174 api::add_evidence($u1->id, $c2->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2175 'error', null, false, null, 1);
2176 } catch (coding_exception $e) {
2177 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2181 public function test_add_evidence_override() {
2182 $this->resetAfterTest(true);
2183 $dg = $this->getDataGenerator();
2184 $lpg = $dg->get_plugin_generator('core_competency');
2186 $u1 = $dg->create_user();
2187 $u1ctx = context_user::instance($u1->id);
2188 $f1 = $lpg->create_framework();
2189 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2191 // Creating an evidence with minimal information.
2192 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2193 'error');
2194 $evidence->read();
2195 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2196 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2197 $this->assertSame(null, $uc->get('grade')); // We overrode with 'null'.
2198 $this->assertSame(null, $uc->get('proficiency'));
2199 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2200 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2201 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get('action'));
2202 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2203 $this->assertEquals('error', $evidence->get('desccomponent'));
2204 $this->assertSame(null, $evidence->get('desca'));
2205 $this->assertSame(null, $evidence->get('url'));
2206 $this->assertSame(null, $evidence->get('grade')); // We overrode with 'null'.
2207 $this->assertSame(null, $evidence->get('actionuserid'));
2209 // Creating an evidence with a grade information.
2210 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2211 'error', null, false, null, 3);
2212 $evidence->read();
2213 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2214 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2215 $this->assertEquals(3, $uc->get('grade'));
2216 $this->assertEquals(true, $uc->get('proficiency'));
2217 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2218 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2219 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get('action'));
2220 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2221 $this->assertEquals('error', $evidence->get('desccomponent'));
2222 $this->assertSame(null, $evidence->get('desca'));
2223 $this->assertSame(null, $evidence->get('url'));
2224 $this->assertEquals(3, $evidence->get('grade'));
2225 $this->assertSame(null, $evidence->get('actionuserid'));
2227 // Creating an evidence with another grade information.
2228 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2229 'error', null, false, null, 1);
2230 $evidence->read();
2231 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2232 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get('status'));
2233 $this->assertEquals(1, $uc->get('grade'));
2234 $this->assertEquals(0, $uc->get('proficiency'));
2235 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2236 $this->assertEquals($u1ctx->id, $evidence->get('contextid'));
2237 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get('action'));
2238 $this->assertEquals('invaliddata', $evidence->get('descidentifier'));
2239 $this->assertEquals('error', $evidence->get('desccomponent'));
2240 $this->assertSame(null, $evidence->get('desca'));
2241 $this->assertSame(null, $evidence->get('url'));
2242 $this->assertEquals(1, $evidence->get('grade'));
2243 $this->assertSame(null, $evidence->get('actionuserid'));
2245 // Creating reverting the grade and send for review.
2246 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2247 'error', null, true);
2248 $evidence->read();
2249 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2250 $this->assertSame(null, $uc->get('grade'));
2251 $this->assertSame(null, $uc->get('proficiency'));
2252 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get('status'));
2253 $this->assertSame(null, $evidence->get('grade'));
2256 public function test_add_evidence_and_send_for_review() {
2257 $this->resetAfterTest(true);
2258 $dg = $this->getDataGenerator();
2259 $lpg = $dg->get_plugin_generator('core_competency');
2261 $u1 = $dg->create_user();
2262 $u1ctx = context_user::instance($u1->id);
2263 $f1 = $lpg->create_framework();
2264 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2266 // Non-existing user competencies are created up for review.
2267 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2268 'error', null, true);
2269 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2270 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get('status'));
2272 // Existing user competencies sent for review don't change.
2273 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2274 'error', null, true);
2275 $uc->read();
2276 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get('status'));
2278 // A user competency with a status non-idle won't change.
2279 $uc->set('status', \core_competency\user_competency::STATUS_IN_REVIEW);
2280 $uc->update();
2281 $evidence = api::add_evidence($u1->id, $c1->get('id'), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2282 'error', null, true);
2283 $uc->read();
2284 $this->assertEquals(\core_competency\user_competency::STATUS_IN_REVIEW, $uc->get('status'));
2288 * Test add evidence for existing user_competency.
2290 public function test_add_evidence_existing_user_competency() {
2291 $this->resetAfterTest(true);
2292 $dg = $this->getDataGenerator();
2293 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2295 $syscontext = context_system::instance();
2297 // Create users.
2298 $user = $dg->create_user();
2299 $this->setUser($user);
2301 // Create a framework and assign competencies.
2302 $framework = $lpg->create_framework();
2303 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2304 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2305 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2306 $uc = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get('id')));
2307 $this->assertSame(null, $uc->get('grade'));
2308 $this->assertSame(null, $uc->get('proficiency'));
2310 // Create an evidence and check it was created with the right usercomptencyid and information.
2311 $evidence = api::add_evidence($user->id, $c1->get('id'), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
2312 'invalidevidencedesc', 'core_competency', array('a' => 'b'), false, 'http://moodle.org', 1, 2);
2313 $this->assertEquals(1, \core_competency\evidence::count_records());
2315 $evidence->read();
2316 $uc->read();
2317 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2318 $this->assertEquals('invalidevidencedesc', $evidence->get('descidentifier'));
2319 $this->assertEquals('core_competency', $evidence->get('desccomponent'));
2320 $this->assertEquals((object) array('a' => 'b'), $evidence->get('desca'));
2321 $this->assertEquals('http://moodle.org', $evidence->get('url'));
2322 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get('action'));
2323 $this->assertEquals(2, $evidence->get('actionuserid'));
2324 $this->assertEquals(1, $evidence->get('grade'));
2325 $this->assertEquals(1, $uc->get('grade'));
2326 $this->assertEquals(0, $uc->get('proficiency'));
2330 * Test add evidence for non-existing user_competency.
2332 public function test_add_evidence_no_existing_user_competency() {
2333 $this->resetAfterTest(true);
2334 $dg = $this->getDataGenerator();
2335 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2337 $syscontext = context_system::instance();
2339 // Create users.
2340 $user = $dg->create_user();
2341 $this->setUser($user);
2343 // Create a framework and assign competencies.
2344 $framework = $lpg->create_framework();
2345 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2346 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2347 $this->assertEquals(0, \core_competency\user_competency::count_records());
2349 // Create an evidence without a user competency record.
2350 $evidence = api::add_evidence($user->id, $c1->get('id'), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
2351 'invalidevidencedesc', 'core_competency', 'Hello world!', false, 'http://moodle.org', 1, 2);
2352 $this->assertEquals(1, \core_competency\evidence::count_records());
2353 $this->assertEquals(1, \core_competency\user_competency::count_records());
2355 $uc = \core_competency\user_competency::get_record(array('userid' => $user->id, 'competencyid' => $c1->get('id')));
2356 $evidence->read();
2357 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
2358 $this->assertEquals('invalidevidencedesc', $evidence->get('descidentifier'));
2359 $this->assertEquals('core_competency', $evidence->get('desccomponent'));
2360 $this->assertEquals('Hello world!', $evidence->get('desca'));
2361 $this->assertEquals('http://moodle.org', $evidence->get('url'));
2362 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get('action'));
2363 $this->assertEquals(2, $evidence->get('actionuserid'));
2364 $this->assertEquals(1, $evidence->get('grade'));
2365 $this->assertEquals(1, $uc->get('grade'));
2366 $this->assertEquals(0, $uc->get('proficiency'));
2369 public function test_add_evidence_applies_competency_rules() {
2370 $this->resetAfterTest(true);
2371 $dg = $this->getDataGenerator();
2372 $lpg = $dg->get_plugin_generator('core_competency');
2373 $syscontext = context_system::instance();
2374 $ctxid = $syscontext->id;
2376 $u1 = $dg->create_user();
2378 // Setting up the framework.
2379 $f1 = $lpg->create_framework();
2380 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2381 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
2382 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
2383 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2384 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c2->get('id')));
2385 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2386 $c3a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c3->get('id')));
2387 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2388 $c4a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c4->get('id')));
2389 $c5 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2391 // Setting up the rules.
2392 $c1->set('ruletype', 'core_competency\\competency_rule_all');
2393 $c1->set('ruleoutcome', \core_competency\competency::OUTCOME_COMPLETE);
2394 $c1->update();
2395 $c2->set('ruletype', 'core_competency\\competency_rule_all');
2396 $c2->set('ruleoutcome', \core_competency\competency::OUTCOME_RECOMMEND);
2397 $c2->update();
2398 $c3->set('ruletype', 'core_competency\\competency_rule_all');
2399 $c3->set('ruleoutcome', \core_competency\competency::OUTCOME_EVIDENCE);
2400 $c3->update();
2401 $c4->set('ruletype', 'core_competency\\competency_rule_all');
2402 $c4->set('ruleoutcome', \core_competency\competency::OUTCOME_NONE);
2403 $c4->update();
2405 // Confirm the current data.
2406 $this->assertEquals(0, user_competency::count_records());
2407 $this->assertEquals(0, evidence::count_records());
2409 // Let's do this!
2410 // First let's confirm that evidence not marking a completion have no impact.
2411 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_LOG, 'commentincontext', 'core');
2412 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get('id')));
2413 $this->assertSame(null, $uc1a->get('proficiency'));
2414 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c1->get('id'))));
2416 // Now let's try complete a competency but the rule won't match (not all children are complete).
2417 // The parent (the thing with the rule) will be created but won't have any evidence attached, and not
2418 // not be marked as completed.
2419 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2420 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get('id')));
2421 $this->assertEquals(true, $uc1a->get('proficiency'));
2422 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2423 $this->assertSame(null, $uc1->get('proficiency'));
2424 $this->assertEquals(0, evidence::count_records(array('usercompetencyid' => $uc1->get('id'))));
2426 // Now we complete the other child. That will mark the parent as complete with an evidence.
2427 api::add_evidence($u1->id, $c1b, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2428 $uc1b = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1b->get('id')));
2429 $this->assertEquals(true, $uc1a->get('proficiency'));
2430 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get('id')));
2431 $this->assertEquals(true, $uc1->get('proficiency'));
2432 $this->assertEquals(user_competency::STATUS_IDLE, $uc1->get('status'));
2433 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc1->get('id'))));
2435 // Check rule recommending.
2436 api::add_evidence($u1->id, $c2a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2437 $uc2a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2a->get('id')));
2438 $this->assertEquals(true, $uc1a->get('proficiency'));
2439 $uc2 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get('id')));
2440 $this->assertSame(null, $uc2->get('proficiency'));
2441 $this->assertEquals(user_competency::STATUS_WAITING_FOR_REVIEW, $uc2->get('status'));
2442 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc2->get('id'))));
2444 // Check rule evidence.
2445 api::add_evidence($u1->id, $c3a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2446 $uc3a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3a->get('id')));
2447 $this->assertEquals(true, $uc1a->get('proficiency'));
2448 $uc3 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get('id')));
2449 $this->assertSame(null, $uc3->get('proficiency'));
2450 $this->assertEquals(user_competency::STATUS_IDLE, $uc3->get('status'));
2451 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc3->get('id'))));
2453 // Check rule nothing.
2454 api::add_evidence($u1->id, $c4a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2455 $uc4a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4a->get('id')));
2456 $this->assertEquals(true, $uc1a->get('proficiency'));
2457 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c4->get('id'))));
2459 // Check marking on something that has no parent. This just checks that nothing breaks.
2460 api::add_evidence($u1->id, $c5, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2464 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2465 * grading a user competency in the system context.
2467 public function test_add_evidence_for_user_competency_course_grade_outside_course() {
2468 $this->resetAfterTest(true);
2469 $dg = $this->getDataGenerator();
2470 $syscontext = context_system::instance();
2472 // Create a student.
2473 $student = $dg->create_user();
2475 // Create a competency for the course.
2476 $lpg = $dg->get_plugin_generator('core_competency');
2477 $framework = $lpg->create_framework();
2478 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2480 // Add evidence.
2481 api::add_evidence($student->id, $comp, $syscontext, evidence::ACTION_OVERRIDE,
2482 'commentincontext', 'core', null, false, null, 1);
2484 // Query for user_competency_course data.
2485 $filterparams = array(
2486 'userid' => $student->id,
2487 'competencyid' => $comp->get('id'),
2489 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
2490 // There should be no user_competency_course object created when grading.
2491 $this->assertFalse($usercompcourse);
2495 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2496 * grading a user competency in a course.
2498 public function test_add_evidence_user_competency_course_grade_in_course() {
2499 global $USER;
2501 $this->resetAfterTest(true);
2502 $dg = $this->getDataGenerator();
2504 // Create and assign a current user.
2505 $currentuser = $dg->create_user();
2506 $this->setUser($currentuser);
2508 // Create a course.
2509 $course = $dg->create_course();
2510 $record = array('courseid' => $course->id, 'pushratingstouserplans' => false);
2511 $settings = new course_competency_settings(0, (object) $record);
2512 $settings->create();
2513 $coursecontext = context_course::instance($course->id);
2515 // Create a student and enrol into the course.
2516 $student = $dg->create_user();
2517 $studentarch = get_archetype_roles('student');
2518 $studentrole = array_shift($studentarch);
2519 $dg->role_assign($studentrole->id, $student->id, $coursecontext->id);
2520 $dg->enrol_user($student->id, $course->id, $studentrole->id);
2522 // Create a competency for the course.
2523 $lpg = $dg->get_plugin_generator('core_competency');
2524 $framework = $lpg->create_framework();
2525 // Do not push ratings from course to user plans.
2526 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2527 $lpg->create_course_competency(array('courseid' => $course->id, 'competencyid' => $comp->get('id')));
2529 // Query for user_competency_course data.
2530 $filterparams = array(
2531 'userid' => $student->id,
2532 'competencyid' => $comp->get('id'),
2533 'courseid' => $course->id
2536 // Add evidence that sets a grade to the course.
2537 $evidence = api::add_evidence($student->id, $comp, $coursecontext, evidence::ACTION_OVERRIDE,
2538 'commentincontext', 'core', null, false, null, 3, $USER->id);
2539 // Get user competency course record.
2540 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
2541 // There should be a user_competency_course object when adding a grade.
2542 $this->assertNotEmpty($usercompcourse);
2543 $grade = $evidence->get('grade');
2544 $this->assertEquals($grade, $usercompcourse->get('grade'));
2545 $this->assertEquals(3, $usercompcourse->get('grade'));
2546 $proficiency = $comp->get_proficiency_of_grade($grade);
2547 $this->assertEquals($proficiency, $usercompcourse->get('proficiency'));
2549 // Confirm that the user competency's grade/proficiency has not been affected by the grade.
2550 $usercompetencyparams = [
2551 'userid' => $student->id,
2552 'competencyid' => $comp->get('id'),
2554 $usercompetency = \core_competency\user_competency::get_record($usercompetencyparams);
2555 $this->assertNotEmpty($usercompetency);
2556 $this->assertNotEquals($usercompcourse->get('grade'), $usercompetency->get('grade'));
2557 $this->assertNotEquals($usercompcourse->get('proficiency'), $usercompetency->get('proficiency'));
2560 public function test_observe_course_completed() {
2561 $this->resetAfterTest(true);
2562 $dg = $this->getDataGenerator();
2563 $lpg = $dg->get_plugin_generator('core_competency');
2565 // Set-up users, framework, competencies and course competencies.
2566 $course = $dg->create_course();
2567 $coursectx = context_course::instance($course->id);
2568 $u1 = $dg->create_user();
2569 $f1 = $lpg->create_framework();
2570 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2571 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2572 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2573 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2574 $cc1 = $lpg->create_course_competency(array('competencyid' => $c1->get('id'), 'courseid' => $course->id,
2575 'ruleoutcome' => \core_competency\course_competency::OUTCOME_NONE));
2576 $cc2 = $lpg->create_course_competency(array('competencyid' => $c2->get('id'), 'courseid' => $course->id,
2577 'ruleoutcome' => \core_competency\course_competency::OUTCOME_EVIDENCE));
2578 $cc3 = $lpg->create_course_competency(array('competencyid' => $c3->get('id'), 'courseid' => $course->id,
2579 'ruleoutcome' => \core_competency\course_competency::OUTCOME_RECOMMEND));
2580 $cc4 = $lpg->create_course_competency(array('competencyid' => $c4->get('id'), 'courseid' => $course->id,
2581 'ruleoutcome' => \core_competency\course_competency::OUTCOME_COMPLETE));
2583 $event = \core\event\course_completed::create(array(
2584 'objectid' => 1,
2585 'relateduserid' => $u1->id,
2586 'context' => $coursectx,
2587 'courseid' => $course->id,
2588 'other' => array('relateduserid' => $u1->id)
2590 $this->assertEquals(0, \core_competency\user_competency::count_records());
2591 $this->assertEquals(0, \core_competency\evidence::count_records());
2593 // Let's go!
2594 api::observe_course_completed($event);
2595 $this->assertEquals(3, \core_competency\user_competency::count_records());
2596 $this->assertEquals(3, \core_competency\evidence::count_records());
2598 // Outcome NONE did nothing.
2599 $this->assertFalse(\core_competency\user_competency::record_exists_select('userid = :uid AND competencyid = :cid', array(
2600 'uid' => $u1->id, 'cid' => $c1->get('id')
2601 )));
2603 // Outcome evidence.
2604 $uc2 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get('id')));
2605 $ev2 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc2->get('id')));
2607 $this->assertEquals(null, $uc2->get('grade'));
2608 $this->assertEquals(null, $uc2->get('proficiency'));
2609 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc2->get('status'));
2611 $this->assertEquals('evidence_coursecompleted', $ev2->get('descidentifier'));
2612 $this->assertEquals('core_competency', $ev2->get('desccomponent'));
2613 $this->assertEquals($course->shortname, $ev2->get('desca'));
2614 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev2->get('url'));
2615 $this->assertEquals(null, $ev2->get('grade'));
2616 $this->assertEquals($coursectx->id, $ev2->get('contextid'));
2617 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev2->get('action'));
2618 $this->assertEquals(null, $ev2->get('actionuserid'));
2620 // Outcome recommend.
2621 $uc3 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get('id')));
2622 $ev3 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc3->get('id')));
2624 $this->assertEquals(null, $uc3->get('grade'));
2625 $this->assertEquals(null, $uc3->get('proficiency'));
2626 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc3->get('status'));
2628 $this->assertEquals('evidence_coursecompleted', $ev3->get('descidentifier'));
2629 $this->assertEquals('core_competency', $ev3->get('desccomponent'));
2630 $this->assertEquals($course->shortname, $ev3->get('desca'));
2631 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev3->get('url'));
2632 $this->assertEquals(null, $ev3->get('grade'));
2633 $this->assertEquals($coursectx->id, $ev3->get('contextid'));
2634 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev3->get('action'));
2635 $this->assertEquals(null, $ev3->get('actionuserid'));
2637 // Outcome complete.
2638 $uc4 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4->get('id')));
2639 $ev4 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc4->get('id')));
2641 $this->assertEquals(3, $uc4->get('grade'));
2642 $this->assertEquals(1, $uc4->get('proficiency'));
2643 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc4->get('status'));
2645 $this->assertEquals('evidence_coursecompleted', $ev4->get('descidentifier'));
2646 $this->assertEquals('core_competency', $ev4->get('desccomponent'));
2647 $this->assertEquals($course->shortname, $ev4->get('desca'));
2648 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev4->get('url'));
2649 $this->assertEquals(3, $ev4->get('grade'));
2650 $this->assertEquals($coursectx->id, $ev4->get('contextid'));
2651 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $ev4->get('action'));
2652 $this->assertEquals(null, $ev4->get('actionuserid'));
2655 public function test_list_evidence_in_course() {
2656 global $SITE;
2658 $this->resetAfterTest(true);
2659 $dg = $this->getDataGenerator();
2660 $lpg = $dg->get_plugin_generator('core_competency');
2661 $u1 = $dg->create_user();
2662 $course = $dg->create_course();
2663 $coursecontext = context_course::instance($course->id);
2665 $this->setAdminUser();
2666 $f = $lpg->create_framework();
2667 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
2668 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
2669 $cc = api::add_competency_to_course($course->id, $c->get('id'));
2670 $cc2 = api::add_competency_to_course($course->id, $c2->get('id'));
2672 $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
2673 $page = $pagegenerator->create_instance(array('course' => $course->id));
2675 $cm = get_coursemodule_from_instance('page', $page->id);
2676 $cmcontext = context_module::instance($cm->id);
2677 // Add the competency to the course module.
2678 $ccm = api::add_competency_to_course_module($cm, $c->get('id'));
2680 // Now add the evidence to the course.
2681 $evidence1 = api::add_evidence($u1->id, $c->get('id'), $coursecontext->id, \core_competency\evidence::ACTION_LOG,
2682 'invaliddata', 'error');
2684 $result = api::list_evidence_in_course($u1->id, $course->id, $c->get('id'));
2685 $this->assertEquals($result[0]->get('id'), $evidence1->get('id'));
2687 // Now add the evidence to the course module.
2688 $evidence2 = api::add_evidence($u1->id, $c->get('id'), $cmcontext->id, \core_competency\evidence::ACTION_LOG,
2689 'invaliddata', 'error');
2691 $result = api::list_evidence_in_course($u1->id, $course->id, $c->get('id'), 'timecreated', 'ASC');
2692 $this->assertEquals($evidence1->get('id'), $result[0]->get('id'));
2693 $this->assertEquals($evidence2->get('id'), $result[1]->get('id'));
2696 public function test_list_course_modules_using_competency() {
2697 global $SITE;
2699 $this->resetAfterTest(true);
2700 $dg = $this->getDataGenerator();
2701 $lpg = $dg->get_plugin_generator('core_competency');
2702 $u1 = $dg->create_user();
2703 $u2 = $dg->create_user();
2704 $course = $dg->create_course();
2705 $course2 = $dg->create_course();
2707 $this->setAdminUser();
2708 $f = $lpg->create_framework();
2709 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
2710 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
2711 $cc = api::add_competency_to_course($course->id, $c->get('id'));
2712 $cc2 = api::add_competency_to_course($course->id, $c2->get('id'));
2714 // First check we get an empty list when there are no links.
2715 $expected = array();
2716 $result = api::list_course_modules_using_competency($c->get('id'), $course->id);
2717 $this->assertEquals($expected, $result);
2719 $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
2720 $page = $pagegenerator->create_instance(array('course' => $course->id));
2722 $cm = get_coursemodule_from_instance('page', $page->id);
2723 // Add a link and list again.
2724 $ccm = api::add_competency_to_course_module($cm, $c->get('id'));
2725 $expected = array($cm->id);
2726 $result = api::list_course_modules_using_competency($c->get('id'), $course->id);
2727 $this->assertEquals($expected, $result);
2729 // Check a different course.
2730 $expected = array();
2731 $result = api::list_course_modules_using_competency($c->get('id'), $course2->id);
2732 $this->assertEquals($expected, $result);
2734 // Remove the link and check again.
2735 $result = api::remove_competency_from_course_module($cm, $c->get('id'));
2736 $expected = true;
2737 $this->assertEquals($expected, $result);
2738 $expected = array();
2739 $result = api::list_course_modules_using_competency($c->get('id'), $course->id);
2740 $this->assertEquals($expected, $result);
2742 // Now add 2 links.
2743 api::add_competency_to_course_module($cm, $c->get('id'));
2744 api::add_competency_to_course_module($cm, $c2->get('id'));
2745 $result = api::list_course_module_competencies_in_course_module($cm->id);
2746 $this->assertEquals($result[0]->get('competencyid'), $c->get('id'));
2747 $this->assertEquals($result[1]->get('competencyid'), $c2->get('id'));
2749 // Now re-order.
2750 api::reorder_course_module_competency($cm, $c->get('id'), $c2->get('id'));
2751 $result = api::list_course_module_competencies_in_course_module($cm->id);
2752 $this->assertEquals($result[0]->get('competencyid'), $c2->get('id'));
2753 $this->assertEquals($result[1]->get('competencyid'), $c->get('id'));
2755 // And re-order again.
2756 api::reorder_course_module_competency($cm, $c->get('id'), $c2->get('id'));
2757 $result = api::list_course_module_competencies_in_course_module($cm->id);
2758 $this->assertEquals($result[0]->get('competencyid'), $c->get('id'));
2759 $this->assertEquals($result[1]->get('competencyid'), $c2->get('id'));
2761 // Now get the course competency and coursemodule competency together.
2762 $result = api::list_course_module_competencies($cm->id);
2763 // Now we should have an array and each element of the array should have a competency and
2764 // a coursemodulecompetency.
2765 foreach ($result as $instance) {
2766 $cmc = $instance['coursemodulecompetency'];
2767 $c = $instance['competency'];
2768 $this->assertEquals($cmc->get('competencyid'), $c->get('id'));
2773 * Test update ruleoutcome for course_competency.
2775 public function test_set_ruleoutcome_course_competency() {
2776 $this->resetAfterTest(true);
2777 $dg = $this->getDataGenerator();
2778 $lpg = $dg->get_plugin_generator('core_competency');
2779 $u1 = $dg->create_user();
2780 $u2 = $dg->create_user();
2781 $course = $dg->create_course();
2783 $this->setAdminUser();
2784 $f = $lpg->create_framework();
2785 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
2786 $cc = api::add_competency_to_course($course->id, $c->get('id'));
2788 // Check record was created with default rule value Evidence.
2789 $this->assertEquals(1, \core_competency\course_competency::count_records());
2790 $recordscc = api::list_course_competencies($course->id);
2791 $this->assertEquals(\core_competency\course_competency::OUTCOME_EVIDENCE,
2792 $recordscc[0]['coursecompetency']->get('ruleoutcome'));
2794 // Check ruleoutcome value is updated to None.
2795 $this->assertTrue(api::set_course_competency_ruleoutcome($recordscc[0]['coursecompetency']->get('id'),
2796 \core_competency\course_competency::OUTCOME_NONE));
2797 $recordscc = api::list_course_competencies($course->id);
2798 $this->assertEquals(\core_competency\course_competency::OUTCOME_NONE, $recordscc[0]['coursecompetency']->get('ruleoutcome'));
2802 * Test validation on grade on user_competency.
2804 public function test_validate_grade_in_user_competency() {
2805 global $DB;
2807 $this->resetAfterTest(true);
2808 $this->setAdminUser();
2809 $dg = $this->getDataGenerator();
2810 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2811 $user = $dg->create_user();
2813 $s1 = $dg->create_scale(array("scale" => "value1, value2"));
2814 $s2 = $dg->create_scale(array("scale" => "value3, value4, value5, value6"));
2816 $scaleconfiguration1 = '[{"scaleid":"'.$s1->id.'"},{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
2817 '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
2818 $scaleconfiguration2 = '[{"scaleid":"'.$s2->id.'"},{"name":"value3","id":1,"scaledefault":1,"proficient":0},'
2819 . '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
2821 // Create a framework with scale configuration1.
2822 $frm = array(
2823 'scaleid' => $s1->id,
2824 'scaleconfiguration' => $scaleconfiguration1
2826 $framework = $lpg->create_framework($frm);
2827 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2829 // Create competency with its own scale configuration.
2830 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'),
2831 'scaleid' => $s2->id,
2832 'scaleconfiguration' => $scaleconfiguration2
2835 // Detecte invalid grade in competency using its framework competency scale.
2836 try {
2837 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get('id'),
2838 'proficiency' => true, 'grade' => 3 ));
2839 $usercompetency->create();
2840 $this->fail('Invalid grade not detected in framework scale');
2841 } catch (\core\invalid_persistent_exception $e) {
2842 $this->assertTrue(true);
2845 // Detecte invalid grade in competency using its own scale.
2846 try {
2847 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get('id'),
2848 'proficiency' => true, 'grade' => 5 ));
2849 $usercompetency->create();
2850 $this->fail('Invalid grade not detected in competency scale');
2851 } catch (\core\invalid_persistent_exception $e) {
2852 $this->assertTrue(true);
2855 // Accept valid grade in competency using its framework competency scale.
2856 try {
2857 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get('id'),
2858 'proficiency' => true, 'grade' => 1 ));
2859 $usercompetency->create();
2860 $this->assertTrue(true);
2861 } catch (\core\invalid_persistent_exception $e) {
2862 $this->fail('Valide grade rejected in framework scale');
2865 // Accept valid grade in competency using its framework competency scale.
2866 try {
2867 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get('id'),
2868 'proficiency' => true, 'grade' => 4 ));
2869 $usercompetency->create();
2870 $this->assertTrue(true);
2871 } catch (\core\invalid_persistent_exception $e) {
2872 $this->fail('Valide grade rejected in competency scale');
2877 * Test when adding competency that belong to hidden framework to plan/template/course.
2879 public function test_hidden_framework() {
2880 $this->resetAfterTest(true);
2881 $this->setAdminUser();
2882 $dg = $this->getDataGenerator();
2883 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2884 $user = $dg->create_user();
2886 // Create a course.
2887 $cat1 = $dg->create_category();
2888 $course = $dg->create_course(array('category' => $cat1->id));
2889 // Create a template.
2890 $template = $lpg->create_template();
2891 // Create a plan.
2892 $plan = $lpg->create_plan(array('userid' => $user->id));
2894 // Create a hidden framework.
2895 $frm = array(
2896 'visible' => false
2898 $framework = $lpg->create_framework($frm);
2899 $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2901 // Linking competency that belong to hidden framework to course.
2902 try {
2903 api::add_competency_to_course($course->id, $competency->get('id'));
2904 $this->fail('A competency belonging to hidden framework can not be linked to course');
2905 } catch (coding_exception $e) {
2906 $this->assertTrue(true);
2909 // Adding competency that belong to hidden framework to template.
2910 try {
2911 api::add_competency_to_template($template->get('id'), $competency->get('id'));
2912 $this->fail('A competency belonging to hidden framework can not be added to template');
2913 } catch (coding_exception $e) {
2914 $this->assertTrue(true);
2917 // Adding competency that belong to hidden framework to plan.
2918 try {
2919 api::add_competency_to_plan($plan->get('id'), $competency->get('id'));
2920 $this->fail('A competency belonging to hidden framework can not be added to plan');
2921 } catch (coding_exception $e) {
2922 $this->assertTrue(true);
2927 * Test when using hidden template in plan/cohort.
2929 public function test_hidden_template() {
2930 $this->resetAfterTest(true);
2931 $this->setAdminUser();
2932 $dg = $this->getDataGenerator();
2933 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2934 $user = $dg->create_user();
2936 // Create a cohort.
2937 $cohort = $dg->create_cohort();
2938 // Create a hidden template.
2939 $template = $lpg->create_template(array('visible' => false));
2941 // Can not link hidden template to plan.
2942 try {
2943 api::create_plan_from_template($template->get('id'), $user->id);
2944 $this->fail('Can not link a hidden template to plan');
2945 } catch (coding_exception $e) {
2946 $this->assertTrue(true);
2949 // Can associate hidden template to cohort.
2950 $templatecohort = api::create_template_cohort($template->get('id'), $cohort->id);
2951 $this->assertInstanceOf('\core_competency\template_cohort', $templatecohort);
2955 * Test that completed plan created form a template does not change when template is modified.
2957 public function test_completed_plan_doesnot_change() {
2958 global $DB;
2960 $this->resetAfterTest(true);
2961 $this->setAdminUser();
2962 $dg = $this->getDataGenerator();
2963 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2964 $user = $dg->create_user();
2966 // Create a framework and assign competencies.
2967 $framework = $lpg->create_framework();
2968 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2969 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2970 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2971 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2973 // Create template and assign competencies.
2974 $tp = $lpg->create_template();
2975 $tpc1 = $lpg->create_template_competency(array('templateid' => $tp->get('id'), 'competencyid' => $c1->get('id')));
2976 $tpc2 = $lpg->create_template_competency(array('templateid' => $tp->get('id'), 'competencyid' => $c2->get('id')));
2977 $tpc3 = $lpg->create_template_competency(array('templateid' => $tp->get('id'), 'competencyid' => $c3->get('id')));
2979 // Create a plan form template and change it status to complete.
2980 $plan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tp->get('id')));
2981 api::complete_plan($plan);
2983 // Check user competency plan created correctly.
2984 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
2985 $ucp = \core_competency\user_competency_plan::get_records();
2986 $this->assertEquals($ucp[0]->get('competencyid'), $c1->get('id'));
2987 $this->assertEquals($ucp[1]->get('competencyid'), $c2->get('id'));
2988 $this->assertEquals($ucp[2]->get('competencyid'), $c3->get('id'));
2990 // Add and remove a competency from the template.
2991 api::add_competency_to_template($tp->get('id'), $c4->get('id'));
2992 api::remove_competency_from_template($tp->get('id'), $c1->get('id'));
2994 // Check that user competency plan did not change.
2995 $competencies = $plan->get_competencies();
2996 $this->assertEquals(3, count($competencies));
2997 $ucp1 = array($c1->get('id'), $c2->get('id'), $c3->get('id'));
2998 $ucp2 = array();
2999 foreach ($competencies as $id => $cmp) {
3000 $ucp2[] = $id;
3002 $this->assertEquals(0, count(array_diff($ucp1, $ucp2)));
3005 protected function setup_framework_for_reset_rules_tests() {
3006 $this->resetAfterTest(true);
3007 $dg = $this->getDataGenerator();
3008 $lpg = $dg->get_plugin_generator('core_competency');
3010 $this->setAdminUser();
3011 $f1 = $lpg->create_framework();
3012 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3013 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3014 $c1a1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3015 $c1a1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a1->get('id')));
3016 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3017 $c1b1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3018 $c1b1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b1->get('id')));
3019 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3020 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3022 $c1->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3023 $c1->set('ruletype', 'core_competency\\competency_rule_all');
3024 $c1->update();
3025 $c1a->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3026 $c1a->set('ruletype', 'core_competency\\competency_rule_all');
3027 $c1a->update();
3028 $c1a1->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3029 $c1a1->set('ruletype', 'core_competency\\competency_rule_all');
3030 $c1a1->update();
3031 $c1b->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3032 $c1b->set('ruletype', 'core_competency\\competency_rule_all');
3033 $c1b->update();
3034 $c2->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3035 $c2->set('ruletype', 'core_competency\\competency_rule_all');
3036 $c2->update();
3038 return array(
3039 'f1' => $f1,
3040 'c1' => $c1,
3041 'c1a' => $c1a,
3042 'c1a1' => $c1a1,
3043 'c1a1a' => $c1a1a,
3044 'c1b' => $c1b,
3045 'c1b1' => $c1b1,
3046 'c1b1a' => $c1b1a,
3047 'c2' => $c2,
3048 'c2a' => $c2a,
3052 public function test_moving_competency_reset_rules_updown() {
3053 $data = $this->setup_framework_for_reset_rules_tests();
3054 $f1 = $data['f1'];
3055 $c1 = $data['c1'];
3056 $c1a = $data['c1a'];
3057 $c1a1 = $data['c1a1'];
3058 $c1a1a = $data['c1a1a'];
3059 $c1b = $data['c1b'];
3060 $c1b1 = $data['c1b1'];
3061 $c1b1a = $data['c1b1a'];
3062 $c2 = $data['c2'];
3063 $c2a = $data['c2a'];
3065 // Moving up and down doesn't change anything.
3066 api::move_down_competency($c1a->get('id'));
3067 $c1->read();
3068 $c1a->read();
3069 $c1a1->read();
3070 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get('ruleoutcome'));
3071 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get('ruleoutcome'));
3072 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get('ruleoutcome'));
3073 api::move_up_competency($c1a->get('id'));
3074 $c1->read();
3075 $c1a->read();
3076 $c1a1->read();
3077 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get('ruleoutcome'));
3078 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get('ruleoutcome'));
3079 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get('ruleoutcome'));
3082 public function test_moving_competency_reset_rules_parent() {
3083 $data = $this->setup_framework_for_reset_rules_tests();
3084 $f1 = $data['f1'];
3085 $c1 = $data['c1'];
3086 $c1a = $data['c1a'];
3087 $c1a1 = $data['c1a1'];
3088 $c1a1a = $data['c1a1a'];
3089 $c1b = $data['c1b'];
3090 $c1b1 = $data['c1b1'];
3091 $c1b1a = $data['c1b1a'];
3092 $c2 = $data['c2'];
3093 $c2a = $data['c2a'];
3095 // Moving out of parent will reset the parent, and the destination.
3096 api::set_parent_competency($c1a->get('id'), $c1b->get('id'));
3097 $c1->read();
3098 $c1a->read();
3099 $c1a1->read();
3100 $c1b->read();
3101 $c2->read();
3102 $this->assertEquals(competency::OUTCOME_NONE, $c1->get('ruleoutcome'));
3103 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get('ruleoutcome'));
3104 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get('ruleoutcome'));
3105 $this->assertEquals(competency::OUTCOME_NONE, $c1b->get('ruleoutcome'));
3106 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3109 public function test_moving_competency_reset_rules_totoplevel() {
3110 $data = $this->setup_framework_for_reset_rules_tests();
3111 $f1 = $data['f1'];
3112 $c1 = $data['c1'];
3113 $c1a = $data['c1a'];
3114 $c1a1 = $data['c1a1'];
3115 $c1a1a = $data['c1a1a'];
3116 $c1b = $data['c1b'];
3117 $c1b1 = $data['c1b1'];
3118 $c1b1a = $data['c1b1a'];
3119 $c2 = $data['c2'];
3120 $c2a = $data['c2a'];
3122 // Moving to top level only affects the initial parent.
3123 api::set_parent_competency($c1a1->get('id'), 0);
3124 $c1->read();
3125 $c1a->read();
3126 $c1a1->read();
3127 $c1b->read();
3128 $c2->read();
3129 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get('ruleoutcome'));
3130 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get('ruleoutcome'));
3131 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get('ruleoutcome'));
3132 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get('ruleoutcome'));
3133 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3136 public function test_moving_competency_reset_rules_fromtoplevel() {
3137 $data = $this->setup_framework_for_reset_rules_tests();
3138 $f1 = $data['f1'];
3139 $c1 = $data['c1'];
3140 $c1a = $data['c1a'];
3141 $c1a1 = $data['c1a1'];
3142 $c1a1a = $data['c1a1a'];
3143 $c1b = $data['c1b'];
3144 $c1b1 = $data['c1b1'];
3145 $c1b1a = $data['c1b1a'];
3146 $c2 = $data['c2'];
3147 $c2a = $data['c2a'];
3149 // Moving from top level only affects the destination parent.
3150 api::set_parent_competency($c2->get('id'), $c1a1->get('id'));
3151 $c1->read();
3152 $c1a->read();
3153 $c1a1->read();
3154 $c1b->read();
3155 $c2->read();
3156 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get('ruleoutcome'));
3157 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get('ruleoutcome'));
3158 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get('ruleoutcome'));
3159 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get('ruleoutcome'));
3160 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3163 public function test_moving_competency_reset_rules_child() {
3164 $data = $this->setup_framework_for_reset_rules_tests();
3165 $f1 = $data['f1'];
3166 $c1 = $data['c1'];
3167 $c1a = $data['c1a'];
3168 $c1a1 = $data['c1a1'];
3169 $c1a1a = $data['c1a1a'];
3170 $c1b = $data['c1b'];
3171 $c1b1 = $data['c1b1'];
3172 $c1b1a = $data['c1b1a'];
3173 $c2 = $data['c2'];
3174 $c2a = $data['c2a'];
3176 // Moving to a child of self resets self, parent and destination.
3177 api::set_parent_competency($c1a->get('id'), $c1a1->get('id'));
3178 $c1->read();
3179 $c1a->read();
3180 $c1a1->read();
3181 $c1b->read();
3182 $c2->read();
3183 $this->assertEquals(competency::OUTCOME_NONE, $c1->get('ruleoutcome'));
3184 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get('ruleoutcome'));
3185 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get('ruleoutcome'));
3186 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get('ruleoutcome'));
3187 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3190 public function test_create_competency_reset_rules() {
3191 $data = $this->setup_framework_for_reset_rules_tests();
3192 $f1 = $data['f1'];
3193 $c1 = $data['c1'];
3194 $c1a = $data['c1a'];
3195 $c1a1 = $data['c1a1'];
3196 $c1a1a = $data['c1a1a'];
3197 $c1b = $data['c1b'];
3198 $c1b1 = $data['c1b1'];
3199 $c1b1a = $data['c1b1a'];
3200 $c2 = $data['c2'];
3201 $c2a = $data['c2a'];
3203 // Adding a new competency resets the rule of its parent.
3204 api::create_competency((object) array('shortname' => 'A', 'parentid' => $c1->get('id'), 'idnumber' => 'A',
3205 'competencyframeworkid' => $f1->get('id')));
3206 $c1->read();
3207 $c1a->read();
3208 $c1a1->read();
3209 $c1b->read();
3210 $c2->read();
3211 $this->assertEquals(competency::OUTCOME_NONE, $c1->get('ruleoutcome'));
3212 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get('ruleoutcome'));
3213 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get('ruleoutcome'));
3214 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get('ruleoutcome'));
3215 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3218 public function test_delete_competency_reset_rules() {
3219 $data = $this->setup_framework_for_reset_rules_tests();
3220 $f1 = $data['f1'];
3221 $c1 = $data['c1'];
3222 $c1a = $data['c1a'];
3223 $c1a1 = $data['c1a1'];
3224 $c1a1a = $data['c1a1a'];
3225 $c1b = $data['c1b'];
3226 $c1b1 = $data['c1b1'];
3227 $c1b1a = $data['c1b1a'];
3228 $c2 = $data['c2'];
3229 $c2a = $data['c2a'];
3231 // Deleting a competency resets the rule of its parent.
3232 api::delete_competency($c1a->get('id'));
3233 $c1->read();
3234 $c1b->read();
3235 $c2->read();
3236 $this->assertEquals(competency::OUTCOME_NONE, $c1->get('ruleoutcome'));
3237 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get('ruleoutcome'));
3238 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get('ruleoutcome'));
3241 public function test_template_has_related_data() {
3242 $this->resetAfterTest(true);
3243 $this->setAdminUser();
3245 $dg = $this->getDataGenerator();
3246 $user = $dg->create_user();
3247 $lpg = $dg->get_plugin_generator('core_competency');
3248 $tpl1 = $lpg->create_template();
3249 $tpl2 = $lpg->create_template();
3251 // Create plans for first template.
3252 $time = time();
3253 $plan1 = $lpg->create_plan(array('templateid' => $tpl1->get('id'), 'userid' => $user->id,
3254 'name' => 'Not good name', 'duedate' => $time + 3600, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
3256 $this->assertTrue(api::template_has_related_data($tpl1->get('id')));
3257 $this->assertFalse(api::template_has_related_data($tpl2->get('id')));
3261 public function test_delete_template_delete_plans() {
3262 $this->resetAfterTest(true);
3263 $this->setAdminUser();
3265 $dg = $this->getDataGenerator();
3266 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
3268 $u1 = $dg->create_user();
3269 $f = $lpg->create_framework();
3270 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
3271 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
3273 $tpl = $lpg->create_template();
3275 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1->get('id'),
3276 'sortorder' => 1));
3277 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c2->get('id'),
3278 'sortorder' => 2));
3280 $p1 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u1->id));
3282 // Check pre-test.
3283 $this->assertTrue(\core_competency\template::record_exists($tpl->get('id')));
3284 $this->assertEquals(2, \core_competency\template_competency::count_competencies($tpl->get('id')));
3285 $this->assertEquals(1, count(\core_competency\plan::get_records(array('templateid' => $tpl->get('id')))));
3287 $result = api::delete_template($tpl->get('id'), true);
3288 $this->assertTrue($result);
3290 // Check that the template does not exist anymore.
3291 $this->assertFalse(\core_competency\template::record_exists($tpl->get('id')));
3293 // Check that associated competencies are also deleted.
3294 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get('id')));
3296 // Check that associated plan are also deleted.
3297 $this->assertEquals(0, count(\core_competency\plan::get_records(array('templateid' => $tpl->get('id')))));
3300 public function test_delete_template_unlink_plans() {
3301 $this->resetAfterTest(true);
3302 $this->setAdminUser();
3304 $dg = $this->getDataGenerator();
3305 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
3307 $u1 = $dg->create_user();
3308 $f = $lpg->create_framework();
3309 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
3310 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get('id')));
3312 $tpl = $lpg->create_template();
3314 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1->get('id'),
3315 'sortorder' => 1));
3316 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c2->get('id'),
3317 'sortorder' => 2));
3319 $p1 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u1->id));
3321 // Check pre-test.
3322 $this->assertTrue(\core_competency\template::record_exists($tpl->get('id')));
3323 $this->assertEquals(2, \core_competency\template_competency::count_competencies($tpl->get('id')));
3324 $this->assertEquals(1, count(\core_competency\plan::get_records(array('templateid' => $tpl->get('id')))));
3326 $result = api::delete_template($tpl->get('id'), false);
3327 $this->assertTrue($result);
3329 // Check that the template does not exist anymore.
3330 $this->assertFalse(\core_competency\template::record_exists($tpl->get('id')));
3332 // Check that associated competencies are also deleted.
3333 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get('id')));
3335 // Check that associated plan still exist but unlink from template.
3336 $plans = \core_competency\plan::get_records(array('id' => $p1->get('id')));
3337 $this->assertEquals(1, count($plans));
3338 $this->assertEquals($plans[0]->get('origtemplateid'), $tpl->get('id'));
3339 $this->assertNull($plans[0]->get('templateid'));
3342 public function test_delete_competency() {
3343 $this->resetAfterTest(true);
3344 $dg = $this->getDataGenerator();
3345 $lpg = $dg->get_plugin_generator('core_competency');
3346 $this->setAdminUser();
3348 $u1 = $dg->create_user();
3350 $f1 = $lpg->create_framework();
3351 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3352 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3353 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3354 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3355 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3356 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3358 // Set rules on parent competency.
3359 $c1->set('ruleoutcome', competency::OUTCOME_EVIDENCE);
3360 $c1->set('ruletype', 'core_competency\\competency_rule_all');
3361 $c1->update();
3363 // If we delete competeny, the related competencies relations and evidences should be deleted.
3364 // Create related competencies using one of c1a competency descendants.
3365 $rc = $lpg->create_related_competency(array(
3366 'competencyid' => $c2->get('id'),
3367 'relatedcompetencyid' => $c11b->get('id')
3369 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3371 // Creating a standard evidence with minimal information.
3372 $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3373 $evidence = $lpg->create_evidence(array('usercompetencyid' => $uc2->get('id')));
3374 $this->assertEquals($uc2->get('id'), $evidence->get('usercompetencyid'));
3375 $uc2->delete();
3377 $this->assertTrue(api::delete_competency($c1a->get('id')));
3378 $this->assertFalse(competency::record_exists($c1a->get('id')));
3380 // Check that on delete, we reset the rule on parent competency.
3381 $c1->read();
3382 $this->assertNull($c1->get('ruletype'));
3383 $this->assertNull($c1->get('ruletype'));
3384 $this->assertEquals(competency::OUTCOME_NONE, $c1->get('ruleoutcome'));
3386 // Check that descendants were also deleted.
3387 $this->assertFalse(competency::record_exists($c1b->get('id')));
3388 $this->assertFalse(competency::record_exists($c11b->get('id')));
3389 $this->assertFalse(competency::record_exists($c12b->get('id')));
3391 // Check if evidence are also deleted.
3392 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3394 // Check if related conpetency relation is deleted.
3395 $this->assertEquals(0, count(api::list_related_competencies($c2->get('id'))));
3397 // Delete a simple competency.
3398 $this->assertTrue(api::delete_competency($c2->get('id')));
3399 $this->assertFalse(competency::record_exists($c2->get('id')));
3402 public function test_delete_competency_used_in_plan() {
3403 $this->resetAfterTest(true);
3404 $dg = $this->getDataGenerator();
3405 $lpg = $dg->get_plugin_generator('core_competency');
3406 $this->setAdminUser();
3408 $u1 = $dg->create_user();
3410 $plan = $lpg->create_plan((object) array('userid' => $u1->id));
3412 $f1 = $lpg->create_framework();
3413 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3414 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3415 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3416 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3417 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3418 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3420 // Add competency to plan.
3421 $pc = $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c11b->get('id')));
3422 // We can not delete a competency , if competency or competency children is associated to plan.
3423 $this->assertFalse(api::delete_competency($c1a->get('id')));
3425 // We can delete the competency if we remove the competency from the plan.
3426 $pc->delete();
3428 $this->assertTrue(api::delete_competency($c1a->get('id')));
3429 $this->assertFalse(competency::record_exists($c1a->get('id')));
3430 $this->assertFalse(competency::record_exists($c1b->get('id')));
3431 $this->assertFalse(competency::record_exists($c11b->get('id')));
3432 $this->assertFalse(competency::record_exists($c12b->get('id')));
3435 public function test_delete_competency_used_in_usercompetency() {
3436 $this->resetAfterTest(true);
3437 $dg = $this->getDataGenerator();
3438 $lpg = $dg->get_plugin_generator('core_competency');
3439 $this->setAdminUser();
3441 $u1 = $dg->create_user();
3443 $f1 = $lpg->create_framework();
3444 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3445 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3446 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3447 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3448 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3449 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3451 // Create user competency.
3452 $uc1 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3454 // We can not delete a competency , if competency or competency children exist in user competency.
3455 $this->assertFalse(api::delete_competency($c1a->get('id')));
3457 // We can delete the competency if we remove the competency from user competency.
3458 $uc1->delete();
3460 $this->assertTrue(api::delete_competency($c1a->get('id')));
3461 $this->assertFalse(competency::record_exists($c1a->get('id')));
3462 $this->assertFalse(competency::record_exists($c1b->get('id')));
3463 $this->assertFalse(competency::record_exists($c11b->get('id')));
3464 $this->assertFalse(competency::record_exists($c12b->get('id')));
3467 public function test_delete_competency_used_in_usercompetencyplan() {
3468 $this->resetAfterTest(true);
3469 $dg = $this->getDataGenerator();
3470 $lpg = $dg->get_plugin_generator('core_competency');
3471 $this->setAdminUser();
3473 $u1 = $dg->create_user();
3475 $plan = $lpg->create_plan((object) array('userid' => $u1->id));
3477 $f1 = $lpg->create_framework();
3478 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3479 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3480 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3481 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3482 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3483 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3485 // Create user competency plan.
3486 $uc2 = $lpg->create_user_competency_plan(array(
3487 'userid' => $u1->id,
3488 'competencyid' => $c11b->get('id'),
3489 'planid' => $plan->get('id')
3492 // We can not delete a competency , if competency or competency children exist in user competency plan.
3493 $this->assertFalse(api::delete_competency($c1a->get('id')));
3495 // We can delete the competency if we remove the competency from user competency plan.
3496 $uc2->delete();
3498 $this->assertTrue(api::delete_competency($c1a->get('id')));
3499 $this->assertFalse(competency::record_exists($c1a->get('id')));
3500 $this->assertFalse(competency::record_exists($c1b->get('id')));
3501 $this->assertFalse(competency::record_exists($c11b->get('id')));
3502 $this->assertFalse(competency::record_exists($c12b->get('id')));
3505 public function test_delete_competency_used_in_template() {
3506 $this->resetAfterTest(true);
3507 $dg = $this->getDataGenerator();
3508 $lpg = $dg->get_plugin_generator('core_competency');
3509 $this->setAdminUser();
3511 $template = $lpg->create_template();
3513 $f1 = $lpg->create_framework();
3514 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3515 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3516 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3517 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3518 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3519 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3521 // Add competency to a template.
3522 $tc = $lpg->create_template_competency(array(
3523 'templateid' => $template->get('id'),
3524 'competencyid' => $c11b->get('id')
3526 // We can not delete a competency , if competency or competency children is linked to template.
3527 $this->assertFalse(api::delete_competency($c1a->get('id')));
3529 // We can delete the competency if we remove the competency from template.
3530 $tc->delete();
3532 $this->assertTrue(api::delete_competency($c1a->get('id')));
3533 $this->assertFalse(competency::record_exists($c1a->get('id')));
3534 $this->assertFalse(competency::record_exists($c1b->get('id')));
3535 $this->assertFalse(competency::record_exists($c11b->get('id')));
3536 $this->assertFalse(competency::record_exists($c12b->get('id')));
3539 public function test_delete_competency_used_in_course() {
3540 $this->resetAfterTest(true);
3541 $dg = $this->getDataGenerator();
3542 $lpg = $dg->get_plugin_generator('core_competency');
3543 $this->setAdminUser();
3545 $cat1 = $dg->create_category();
3547 $course = $dg->create_course(array('category' => $cat1->id));
3549 $f1 = $lpg->create_framework();
3550 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3551 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3552 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3553 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3554 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3555 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3557 // Add competency to course.
3558 $cc = $lpg->create_course_competency(array(
3559 'courseid' => $course->id,
3560 'competencyid' => $c11b->get('id')
3563 // We can not delete a competency if the competency or competencies children is linked to a course.
3564 $this->assertFalse(api::delete_competency($c1a->get('id')));
3566 // We can delete the competency if we remove the competency from course.
3567 $cc->delete();
3569 $this->assertTrue(api::delete_competency($c1a->get('id')));
3570 $this->assertFalse(competency::record_exists($c1a->get('id')));
3571 $this->assertFalse(competency::record_exists($c1b->get('id')));
3572 $this->assertFalse(competency::record_exists($c11b->get('id')));
3573 $this->assertFalse(competency::record_exists($c12b->get('id')));
3576 public function test_delete_framework() {
3577 $this->resetAfterTest(true);
3578 $dg = $this->getDataGenerator();
3579 $lpg = $dg->get_plugin_generator('core_competency');
3580 $this->setAdminUser();
3582 $u1 = $dg->create_user();
3584 $f1 = $lpg->create_framework();
3585 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3586 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3587 $c2id = $c2->get('id');
3588 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3589 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3590 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3591 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3593 // If we delete framework, the related competencies relations and evidences should be deleted.
3594 // Create related competencies using one of c1a competency descendants.
3595 $rc = $lpg->create_related_competency(array(
3596 'competencyid' => $c2->get('id'),
3597 'relatedcompetencyid' => $c11b->get('id')
3599 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3601 // Creating a standard evidence with minimal information.
3602 $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3603 $evidence = $lpg->create_evidence(array('usercompetencyid' => $uc2->get('id')));
3604 $this->assertEquals($uc2->get('id'), $evidence->get('usercompetencyid'));
3605 $uc2->delete();
3607 $this->assertTrue(api::delete_framework($f1->get('id')));
3608 $this->assertFalse(competency_framework::record_exists($f1->get('id')));
3610 // Check that all competencies were also deleted.
3611 $this->assertFalse(competency::record_exists($c1->get('id')));
3612 $this->assertFalse(competency::record_exists($c2->get('id')));
3613 $this->assertFalse(competency::record_exists($c1a->get('id')));
3614 $this->assertFalse(competency::record_exists($c1b->get('id')));
3615 $this->assertFalse(competency::record_exists($c11b->get('id')));
3616 $this->assertFalse(competency::record_exists($c12b->get('id')));
3618 // Check if evidence are also deleted.
3619 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3621 // Check if related conpetency relation is deleted.
3622 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3624 // Delete a simple framework.
3625 $f2 = $lpg->create_framework();
3626 $this->assertTrue(api::delete_framework($f2->get('id')));
3627 $this->assertFalse(competency_framework::record_exists($f2->get('id')));
3630 public function test_delete_framework_competency_used_in_plan() {
3631 $this->resetAfterTest(true);
3632 $dg = $this->getDataGenerator();
3633 $lpg = $dg->get_plugin_generator('core_competency');
3634 $this->setAdminUser();
3636 $u1 = $dg->create_user();
3638 $plan = $lpg->create_plan((object) array('userid' => $u1->id));
3640 $f1 = $lpg->create_framework();
3641 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3642 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3643 $c2id = $c2->get('id');
3644 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3645 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3646 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3647 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3649 // Create related competencies.
3650 $rc = $lpg->create_related_competency(array(
3651 'competencyid' => $c2->get('id'),
3652 'relatedcompetencyid' => $c11b->get('id')
3654 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3656 // Creating a standard evidence with minimal information.
3657 $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3658 $usercompetencyid = $uc2->get('id');
3659 $evidence = $lpg->create_evidence(array('usercompetencyid' => $usercompetencyid));
3660 $this->assertEquals($uc2->get('id'), $evidence->get('usercompetencyid'));
3661 $uc2->delete();
3663 // Add competency to plan.
3664 $pc = $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $c11b->get('id')));
3665 // We can not delete a framework , if competency or competency children is associated to plan.
3666 $this->assertFalse(api::delete_framework($f1->get('id')));
3667 // Check that none of associated data are deleted.
3668 $this->assertEquals($usercompetencyid, $evidence->read()->get('usercompetencyid'));
3669 $this->assertEquals($c2->get('id'), $rc->read()->get('competencyid'));
3671 // We can delete the competency if we remove the competency from the plan.
3672 $pc->delete();
3674 $this->assertTrue(api::delete_framework($f1->get('id')));
3675 $this->assertFalse(competency::record_exists($c1->get('id')));
3676 $this->assertFalse(competency::record_exists($c2->get('id')));
3677 $this->assertFalse(competency::record_exists($c1a->get('id')));
3678 $this->assertFalse(competency::record_exists($c1b->get('id')));
3679 $this->assertFalse(competency::record_exists($c11b->get('id')));
3680 $this->assertFalse(competency::record_exists($c12b->get('id')));
3681 // Check if evidence are also deleted.
3682 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3684 // Check if related conpetency relation is deleted.
3685 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3688 public function test_delete_framework_competency_used_in_usercompetency() {
3689 $this->resetAfterTest(true);
3690 $dg = $this->getDataGenerator();
3691 $lpg = $dg->get_plugin_generator('core_competency');
3692 $this->setAdminUser();
3694 $u1 = $dg->create_user();
3696 $f1 = $lpg->create_framework();
3697 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3698 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3699 $c2id = $c2->get('id');
3700 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3701 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3702 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3703 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3705 // Create related competencies.
3706 $rc = $lpg->create_related_competency(array(
3707 'competencyid' => $c2->get('id'),
3708 'relatedcompetencyid' => $c11b->get('id')
3710 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3712 // Creating a standard evidence with minimal information.
3713 $uc1 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3714 $usercompetencyid = $uc1->get('id');
3715 $evidence = $lpg->create_evidence(array('usercompetencyid' => $usercompetencyid));
3716 $this->assertEquals($uc1->get('id'), $evidence->get('usercompetencyid'));
3717 $uc1->delete();
3719 // Create user competency.
3720 $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3722 // We can not delete a framework , if competency or competency children exist in user competency.
3723 $this->assertFalse(api::delete_framework($f1->get('id')));
3724 // Check that none of associated data are deleted.
3725 $this->assertEquals($usercompetencyid, $evidence->read()->get('usercompetencyid'));
3726 $this->assertEquals($c2->get('id'), $rc->read()->get('competencyid'));
3728 // We can delete the framework if we remove the competency from user competency.
3729 $uc2->delete();
3731 $this->assertTrue(api::delete_framework($f1->get('id')));
3732 $this->assertFalse(competency::record_exists($c1->get('id')));
3733 $this->assertFalse(competency::record_exists($c2->get('id')));
3734 $this->assertFalse(competency::record_exists($c1a->get('id')));
3735 $this->assertFalse(competency::record_exists($c1b->get('id')));
3736 $this->assertFalse(competency::record_exists($c11b->get('id')));
3737 $this->assertFalse(competency::record_exists($c12b->get('id')));
3738 // Check if evidence are also deleted.
3739 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3741 // Check if related conpetency relation is deleted.
3742 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3745 public function test_delete_framework_competency_used_in_usercompetencyplan() {
3746 $this->resetAfterTest(true);
3747 $dg = $this->getDataGenerator();
3748 $lpg = $dg->get_plugin_generator('core_competency');
3749 $this->setAdminUser();
3751 $u1 = $dg->create_user();
3753 $plan = $lpg->create_plan((object) array('userid' => $u1->id));
3755 $f1 = $lpg->create_framework();
3756 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3757 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3758 $c2id = $c2->get('id');
3759 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3760 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3761 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3762 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3764 // Create related competencies.
3765 $rc = $lpg->create_related_competency(array(
3766 'competencyid' => $c2->get('id'),
3767 'relatedcompetencyid' => $c11b->get('id')
3769 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3771 // Creating a standard evidence with minimal information.
3772 $uc1 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3773 $usercompetencyid = $uc1->get('id');
3774 $evidence = $lpg->create_evidence(array('usercompetencyid' => $usercompetencyid));
3775 $this->assertEquals($uc1->get('id'), $evidence->get('usercompetencyid'));
3776 $uc1->delete();
3778 // Create user competency plan.
3779 $uc2 = $lpg->create_user_competency_plan(array(
3780 'userid' => $u1->id,
3781 'competencyid' => $c11b->get('id'),
3782 'planid' => $plan->get('id')
3785 // We can not delete a framework , if competency or competency children exist in user competency plan.
3786 $this->assertFalse(api::delete_framework($f1->get('id')));
3787 // Check that none of associated data are deleted.
3788 $this->assertEquals($usercompetencyid, $evidence->read()->get('usercompetencyid'));
3789 $this->assertEquals($c2->get('id'), $rc->read()->get('competencyid'));
3791 // We can delete the framework if we remove the competency from user competency plan.
3792 $uc2->delete();
3794 $this->assertTrue(api::delete_framework($f1->get('id')));
3795 $this->assertFalse(competency::record_exists($c1->get('id')));
3796 $this->assertFalse(competency::record_exists($c2->get('id')));
3797 $this->assertFalse(competency::record_exists($c1a->get('id')));
3798 $this->assertFalse(competency::record_exists($c1b->get('id')));
3799 $this->assertFalse(competency::record_exists($c11b->get('id')));
3800 $this->assertFalse(competency::record_exists($c12b->get('id')));
3801 // Check if evidence are also deleted.
3802 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3804 // Check if related conpetency relation is deleted.
3805 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3808 public function test_delete_framework_competency_used_in_template() {
3809 $this->resetAfterTest(true);
3810 $dg = $this->getDataGenerator();
3811 $lpg = $dg->get_plugin_generator('core_competency');
3812 $this->setAdminUser();
3814 $u1 = $dg->create_user();
3815 $template = $lpg->create_template();
3817 $f1 = $lpg->create_framework();
3818 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3819 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3820 $c2id = $c2->get('id');
3821 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3822 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3823 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3824 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3826 // Create related competencies.
3827 $rc = $lpg->create_related_competency(array(
3828 'competencyid' => $c2->get('id'),
3829 'relatedcompetencyid' => $c11b->get('id')
3831 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3833 // Creating a standard evidence with minimal information.
3834 $uc1 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3835 $usercompetencyid = $uc1->get('id');
3836 $evidence = $lpg->create_evidence(array('usercompetencyid' => $usercompetencyid));
3837 $this->assertEquals($uc1->get('id'), $evidence->get('usercompetencyid'));
3838 $uc1->delete();
3840 // Add competency to a template.
3841 $tc = $lpg->create_template_competency(array(
3842 'templateid' => $template->get('id'),
3843 'competencyid' => $c11b->get('id')
3845 // We can not delete a framework , if competency or competency children is linked to template.
3846 $this->assertFalse(api::delete_framework($f1->get('id')));
3847 // Check that none of associated data are deleted.
3848 $this->assertEquals($usercompetencyid, $evidence->read()->get('usercompetencyid'));
3849 $this->assertEquals($c2->get('id'), $rc->read()->get('competencyid'));
3851 // We can delete the framework if we remove the competency from template.
3852 $tc->delete();
3854 $this->assertTrue(api::delete_framework($f1->get('id')));
3855 $this->assertFalse(competency::record_exists($c1->get('id')));
3856 $this->assertFalse(competency::record_exists($c2->get('id')));
3857 $this->assertFalse(competency::record_exists($c1a->get('id')));
3858 $this->assertFalse(competency::record_exists($c1b->get('id')));
3859 $this->assertFalse(competency::record_exists($c11b->get('id')));
3860 $this->assertFalse(competency::record_exists($c12b->get('id')));
3861 // Check if evidence are also deleted.
3862 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3864 // Check if related conpetency relation is deleted.
3865 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3868 public function test_delete_framework_competency_used_in_course() {
3869 $this->resetAfterTest(true);
3870 $dg = $this->getDataGenerator();
3871 $lpg = $dg->get_plugin_generator('core_competency');
3872 $this->setAdminUser();
3874 $cat1 = $dg->create_category();
3875 $u1 = $dg->create_user();
3876 $course = $dg->create_course(array('category' => $cat1->id));
3878 $f1 = $lpg->create_framework();
3879 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3880 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
3881 $c2id = $c2->get('id');
3882 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1->get('id')));
3883 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1a->get('id')));
3884 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3885 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'parentid' => $c1b->get('id')));
3887 // Create related competencies.
3888 $rc = $lpg->create_related_competency(array(
3889 'competencyid' => $c2->get('id'),
3890 'relatedcompetencyid' => $c11b->get('id')
3892 $this->assertEquals($c11b->get('id'), $rc->get('relatedcompetencyid'));
3894 // Creating a standard evidence with minimal information.
3895 $uc1 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get('id')));
3896 $usercompetencyid = $uc1->get('id');
3897 $evidence = $lpg->create_evidence(array('usercompetencyid' => $usercompetencyid));
3898 $this->assertEquals($uc1->get('id'), $evidence->get('usercompetencyid'));
3899 $uc1->delete();
3901 // Add competency to course.
3902 $cc = $lpg->create_course_competency(array(
3903 'courseid' => $course->id,
3904 'competencyid' => $c11b->get('id')
3907 // We can not delete a framework if the competency or competencies children is linked to a course.
3908 $this->assertFalse(api::delete_framework($f1->get('id')));
3909 // Check that none of associated data are deleted.
3910 $this->assertEquals($usercompetencyid, $evidence->read()->get('usercompetencyid'));
3911 $this->assertEquals($c2->get('id'), $rc->read()->get('competencyid'));
3913 // We can delete the framework if we remove the competency from course.
3914 $cc->delete();
3916 $this->assertTrue(api::delete_framework($f1->get('id')));
3917 $this->assertFalse(competency::record_exists($c1->get('id')));
3918 $this->assertFalse(competency::record_exists($c2->get('id')));
3919 $this->assertFalse(competency::record_exists($c1a->get('id')));
3920 $this->assertFalse(competency::record_exists($c1b->get('id')));
3921 $this->assertFalse(competency::record_exists($c11b->get('id')));
3922 $this->assertFalse(competency::record_exists($c12b->get('id')));
3923 // Check if evidence are also deleted.
3924 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get('id'))));
3926 // Check if related conpetency relation is deleted.
3927 $this->assertEquals(0, count(\core_competency\related_competency::get_multiple_relations(array($c2id))));
3930 public function test_grade_competency_in_course_permissions() {
3931 $this->resetAfterTest();
3932 $dg = $this->getDataGenerator();
3934 $c1 = $dg->create_course();
3935 $c2 = $dg->create_course();
3936 $sysctx = context_system::instance();
3937 $c1ctx = context_course::instance($c1->id);
3938 $c2ctx = context_course::instance($c2->id);
3940 $teacher1 = $dg->create_user();
3941 $noneditingteacher = $dg->create_user();
3942 $student1 = $dg->create_user();
3943 $student2 = $dg->create_user();
3944 $notstudent1 = $dg->create_user();
3946 $lpg = $dg->get_plugin_generator('core_competency');
3947 $framework = $lpg->create_framework();
3948 $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
3949 $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
3950 $lpg->create_course_competency(array('courseid' => $c1->id, 'competencyid' => $comp1->get('id')));
3952 $studentarch = get_archetype_roles('student');
3953 $studentrole = array_shift($studentarch);
3955 $gradablerole = $dg->create_role();
3956 assign_capability('moodle/competency:coursecompetencygradable', CAP_ALLOW, $gradablerole, $sysctx->id);
3958 $notgradablerole = $dg->create_role();
3959 assign_capability('moodle/competency:coursecompetencygradable', CAP_PROHIBIT, $notgradablerole, $sysctx->id);
3961 $canviewucrole = $dg->create_role();
3962 assign_capability('moodle/competency:usercompetencyview', CAP_ALLOW, $canviewucrole, $sysctx->id);
3964 $cannotviewcomp = $dg->create_role();
3965 assign_capability('moodle/competency:competencyview', CAP_PROHIBIT, $cannotviewcomp, $sysctx->id);
3967 $canmanagecomp = $dg->create_role();
3968 assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $canmanagecomp, $sysctx->id);
3970 $cangraderole = $dg->create_role();
3971 assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $cangraderole, $sysctx->id);
3973 // Enrol s1 and s2 as students in course 1.
3974 $dg->enrol_user($student1->id, $c1->id, $studentrole->id);
3975 $dg->enrol_user($student2->id, $c1->id, $studentrole->id);
3977 // Mark the s2 as not being 'gradable'.
3978 $dg->role_assign($notgradablerole, $student2->id, $c1ctx->id);
3980 // Mark the 'non a student' as 'gradable' throughout the site.
3981 $dg->role_assign($gradablerole, $notstudent1->id, $sysctx->id);
3983 // From now we'll iterate over each permission.
3984 accesslib_clear_all_caches_for_unit_testing();
3985 $this->setUser($teacher1);
3987 $this->assertExceptionWithGradeCompetencyInCourse('required_capability_exception', 'View a user competency',
3988 $c1->id, $student1->id, $comp1->get('id'));
3990 // Give permission to view competencies.
3991 $dg->role_assign($canviewucrole, $teacher1->id, $c1ctx->id);
3992 accesslib_clear_all_caches_for_unit_testing();
3993 $this->assertExceptionWithGradeCompetencyInCourse('required_capability_exception', 'Set competency rating',
3994 $c1->id, $student1->id, $comp1->get('id'));
3996 // Give permission to rate.
3997 $dg->role_assign($cangraderole, $teacher1->id, $c1ctx->id);
3998 accesslib_clear_all_caches_for_unit_testing();
3999 $this->assertSuccessWithGradeCompetencyInCourse($c1->id, $student1->id, $comp1->get('id'));
4001 // Remove permssion to read competencies, this leads to error.
4002 $dg->role_assign($cannotviewcomp, $teacher1->id, $sysctx->id);
4003 accesslib_clear_all_caches_for_unit_testing();
4004 $this->assertExceptionWithGradeCompetencyInCourse('required_capability_exception', 'View competency frameworks',
4005 $c1->id, $student1->id, $comp1->get('id'));
4007 // Give permssion to manage course competencies, this leads to success.
4008 $dg->role_assign($canmanagecomp, $teacher1->id, $sysctx->id);
4009 accesslib_clear_all_caches_for_unit_testing();
4010 $this->assertSuccessWithGradeCompetencyInCourse($c1->id, $student1->id, $comp1->get('id'));
4012 // Try to grade a user that is not gradable, lead to errors.
4013 $this->assertExceptionWithGradeCompetencyInCourse('coding_exception', 'The competency may not be rated at this time.',
4014 $c1->id, $student2->id, $comp1->get('id'));
4016 // Try to grade a competency not in the course.
4017 $this->assertExceptionWithGradeCompetencyInCourse('coding_exception', 'The competency does not belong to this course',
4018 $c1->id, $student1->id, $comp2->get('id'));
4020 // Try to grade a user that is not enrolled, even though they are 'gradable'.
4021 $this->assertExceptionWithGradeCompetencyInCourse('coding_exception', 'The competency may not be rated at this time.',
4022 $c1->id, $notstudent1->id, $comp1->get('id'));
4024 // Give permission for non-editing teacher to grade.
4025 $dg->role_assign($canviewucrole, $noneditingteacher->id, $c1ctx->id);
4026 $dg->role_assign($cangraderole, $noneditingteacher->id, $c1ctx->id);
4027 $this->setUser($noneditingteacher);
4029 accesslib_clear_all_caches_for_unit_testing();
4030 $this->assertSuccessWithGradeCompetencyInCourse($c1->id, $student1->id, $comp1->get('id'));
4034 * Assert that a competency was graded in a course.
4036 * @param int $courseid The course ID.
4037 * @param int $userid The user ID.
4038 * @param int $compid The competency ID.
4039 * @param int $grade The grade.
4041 protected function assertSuccessWithGradeCompetencyInCourse($courseid, $userid, $compid, $grade = 1) {
4042 $beforecount = evidence::count_records();
4043 api::grade_competency_in_course($courseid, $userid, $compid, $grade);
4044 $this->assertEquals($beforecount + 1, evidence::count_records());
4045 $uc = user_competency::get_record(array('userid' => $userid, 'competencyid' => $compid));
4046 $records = evidence::get_records(array(), 'id', 'DESC', 0, 1);
4047 $evidence = array_pop($records);
4048 $this->assertEquals($uc->get('id'), $evidence->get('usercompetencyid'));
4052 * Assert that grading a competency in course throws an exception.
4054 * @param string $exceptiontype The exception type.
4055 * @param string $exceptiontest The exceptiont text.
4056 * @param int $courseid The course ID.
4057 * @param int $userid The user ID.
4058 * @param int $compid The competency ID.
4059 * @param int $grade The grade.
4061 protected function assertExceptionWithGradeCompetencyInCourse($exceptiontype, $exceptiontext, $courseid, $userid, $compid,
4062 $grade = 1) {
4064 $raised = false;
4065 try {
4066 api::grade_competency_in_course($courseid, $userid, $compid, $grade);
4067 } catch (moodle_exception $e) {
4068 $raised = true;
4069 $this->assertInstanceOf($exceptiontype, $e);
4070 $this->assertRegExp('@' . $exceptiontext . '@', $e->getMessage());
4073 if (!$raised) {
4074 $this->fail('Grading should not be allowed.');
4079 * Test list of evidences for plan completed and not completed.
4081 public function test_list_evidence() {
4082 global $DB;
4084 $this->resetAfterTest(true);
4085 $dg = $this->getDataGenerator();
4086 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
4088 $syscontext = context_system::instance();
4090 // Create users.
4091 $user = $dg->create_user();
4092 $this->setUser($user);
4094 // Create a framework and assign competencies.
4095 $framework = $lpg->create_framework();
4096 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4097 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4099 // Create 2 user plans and add competency to each plan.
4100 $p1 = $lpg->create_plan(array('userid' => $user->id));
4101 $p2 = $lpg->create_plan(array('userid' => $user->id));
4102 $pc1 = $lpg->create_plan_competency(array('planid' => $p1->get('id'), 'competencyid' => $c1->get('id')));
4103 $pc2 = $lpg->create_plan_competency(array('planid' => $p2->get('id'), 'competencyid' => $c1->get('id')));
4105 // Create user competency and add an evidence.
4106 $uc = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get('id')));
4107 $e1 = $lpg->create_evidence(array('usercompetencyid' => $uc->get('id')));
4109 // Check both plans as one evidence.
4110 $this->assertEquals(1, count(api::list_evidence($user->id, $c1->get('id'), $p1->get('id'))));
4111 $this->assertEquals(1, count(api::list_evidence($user->id, $c1->get('id'), $p2->get('id'))));
4113 // Complete second plan.
4114 $p2->set('status', plan::STATUS_COMPLETE);
4115 $p2->update();
4117 // Add another evidence for the same competency, but in the future (time + 1).
4118 $e2 = $lpg->create_evidence(array('usercompetencyid' => $uc->get('id')));
4119 $evidencesql = "UPDATE {" . evidence::TABLE . "} SET timecreated = :currenttime WHERE id = :evidenceid";
4120 $DB->execute($evidencesql, array('currenttime' => time() + 1, 'evidenceid' => $e2->get('id')));
4122 // Check that the first plan, which is not completed, has all the evidence.
4123 $this->assertEquals(2, count(api::list_evidence($user->id, $c1->get('id'), $p1->get('id'))));
4125 // Check that the second plan, completed before the new evidence, only has the first piece of evidence.
4126 $listevidences = api::list_evidence($user->id, $c1->get('id'), $p2->get('id'));
4127 $this->assertEquals(1, count($listevidences));
4128 $this->assertEquals($e1->get('id'), $listevidences[$e1->get('id')]->get('id'));
4132 * Get a user competency in a course.
4134 public function test_get_user_competency_in_course() {
4135 $this->resetAfterTest(true);
4136 $dg = $this->getDataGenerator();
4137 $lpg = $dg->get_plugin_generator('core_competency');
4138 $this->setAdminUser();
4140 $user = $dg->create_user();
4141 $c1 = $dg->create_course();
4143 // Enrol the user so they can be rated in the course.
4144 $studentarch = get_archetype_roles('student');
4145 $studentrole = array_shift($studentarch);
4146 $coursecontext = context_course::instance($c1->id);
4147 $dg->role_assign($studentrole->id, $user->id, $coursecontext->id);
4148 $dg->enrol_user($user->id, $c1->id, $studentrole->id);
4150 $framework = $lpg->create_framework();
4151 $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4152 $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4153 $lpg->create_course_competency(array('competencyid' => $comp1->get('id'), 'courseid' => $c1->id));
4154 $lpg->create_course_competency(array('competencyid' => $comp2->get('id'), 'courseid' => $c1->id));
4156 // Create a user competency for comp1.
4157 api::grade_competency_in_course($c1, $user->id, $comp1->get('id'), 3, 'Unit test');
4159 // Test for competency already exist in user_competency.
4160 $uc = api::get_user_competency_in_course($c1->id, $user->id, $comp1->get('id'));
4161 $this->assertEquals($comp1->get('id'), $uc->get('competencyid'));
4162 $this->assertEquals($user->id, $uc->get('userid'));
4163 $this->assertEquals(3, $uc->get('grade'));
4164 $this->assertEquals(true, $uc->get('proficiency'));
4166 // Test for competency does not exist in user_competency.
4167 $uc2 = api::get_user_competency_in_course($c1->id, $user->id, $comp2->get('id'));
4168 $this->assertEquals($comp2->get('id'), $uc2->get('competencyid'));
4169 $this->assertEquals($user->id, $uc2->get('userid'));
4170 $this->assertEquals(null, $uc2->get('grade'));
4171 $this->assertEquals(null, $uc2->get('proficiency'));
4175 * Test course statistics api functions.
4177 public function test_course_statistics() {
4178 $this->resetAfterTest(true);
4179 $dg = $this->getDataGenerator();
4180 $lpg = $dg->get_plugin_generator('core_competency');
4181 $this->setAdminUser();
4183 $u1 = $dg->create_user();
4184 $u2 = $dg->create_user();
4185 $u3 = $dg->create_user();
4186 $u4 = $dg->create_user();
4187 $c1 = $dg->create_course();
4188 $framework = $lpg->create_framework();
4189 // Enrol students in the course.
4190 $studentarch = get_archetype_roles('student');
4191 $studentrole = array_shift($studentarch);
4192 $coursecontext = context_course::instance($c1->id);
4193 $dg->role_assign($studentrole->id, $u1->id, $coursecontext->id);
4194 $dg->enrol_user($u1->id, $c1->id, $studentrole->id);
4195 $dg->role_assign($studentrole->id, $u2->id, $coursecontext->id);
4196 $dg->enrol_user($u2->id, $c1->id, $studentrole->id);
4197 $dg->role_assign($studentrole->id, $u3->id, $coursecontext->id);
4198 $dg->enrol_user($u3->id, $c1->id, $studentrole->id);
4199 $dg->role_assign($studentrole->id, $u4->id, $coursecontext->id);
4200 $dg->enrol_user($u4->id, $c1->id, $studentrole->id);
4202 // Create 6 competencies.
4203 $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4204 $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4205 $comp3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4206 $comp4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4207 $comp5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4208 $comp6 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4210 // Link 6 out of 6 to a course.
4211 $lpg->create_course_competency(array('competencyid' => $comp1->get('id'), 'courseid' => $c1->id));
4212 $lpg->create_course_competency(array('competencyid' => $comp2->get('id'), 'courseid' => $c1->id));
4213 $lpg->create_course_competency(array('competencyid' => $comp3->get('id'), 'courseid' => $c1->id));
4214 $lpg->create_course_competency(array('competencyid' => $comp4->get('id'), 'courseid' => $c1->id));
4215 $lpg->create_course_competency(array('competencyid' => $comp5->get('id'), 'courseid' => $c1->id));
4216 $lpg->create_course_competency(array('competencyid' => $comp6->get('id'), 'courseid' => $c1->id));
4218 // Rate some competencies.
4219 // User 1.
4220 api::grade_competency_in_course($c1, $u1->id, $comp1->get('id'), 4, 'Unit test');
4221 api::grade_competency_in_course($c1, $u1->id, $comp2->get('id'), 4, 'Unit test');
4222 api::grade_competency_in_course($c1, $u1->id, $comp3->get('id'), 4, 'Unit test');
4223 api::grade_competency_in_course($c1, $u1->id, $comp4->get('id'), 4, 'Unit test');
4224 // User 2.
4225 api::grade_competency_in_course($c1, $u2->id, $comp1->get('id'), 1, 'Unit test');
4226 api::grade_competency_in_course($c1, $u2->id, $comp2->get('id'), 1, 'Unit test');
4227 api::grade_competency_in_course($c1, $u2->id, $comp3->get('id'), 1, 'Unit test');
4228 api::grade_competency_in_course($c1, $u2->id, $comp4->get('id'), 1, 'Unit test');
4229 // User 3.
4230 api::grade_competency_in_course($c1, $u3->id, $comp1->get('id'), 3, 'Unit test');
4231 api::grade_competency_in_course($c1, $u3->id, $comp2->get('id'), 3, 'Unit test');
4232 // User 4.
4233 api::grade_competency_in_course($c1, $u4->id, $comp1->get('id'), 2, 'Unit test');
4234 api::grade_competency_in_course($c1, $u4->id, $comp2->get('id'), 2, 'Unit test');
4236 // OK we have enough data - lets call some API functions and check for expected results.
4238 $result = api::count_proficient_competencies_in_course_for_user($c1->id, $u1->id);
4239 $this->assertEquals(4, $result);
4240 $result = api::count_proficient_competencies_in_course_for_user($c1->id, $u2->id);
4241 $this->assertEquals(0, $result);
4242 $result = api::count_proficient_competencies_in_course_for_user($c1->id, $u3->id);
4243 $this->assertEquals(2, $result);
4244 $result = api::count_proficient_competencies_in_course_for_user($c1->id, $u4->id);
4245 $this->assertEquals(0, $result);
4247 $result = api::get_least_proficient_competencies_for_course($c1->id, 0, 2);
4248 // We should get 5 and 6 in repeatable order.
4249 $valid = false;
4250 if (($comp5->get('id') == $result[0]->get('id')) || ($comp6->get('id') == $result[0]->get('id'))) {
4251 $valid = true;
4253 $this->assertTrue($valid);
4254 $valid = false;
4255 if (($comp5->get('id') == $result[1]->get('id')) || ($comp6->get('id') == $result[1]->get('id'))) {
4256 $valid = true;
4258 $this->assertTrue($valid);
4259 $expected = $result[1]->get('id');
4260 $result = api::get_least_proficient_competencies_for_course($c1->id, 1, 1);
4261 $this->assertEquals($result[0]->get('id'), $expected);
4265 * Test template statistics api functions.
4267 public function test_template_statistics() {
4268 $this->resetAfterTest(true);
4269 $dg = $this->getDataGenerator();
4270 $lpg = $dg->get_plugin_generator('core_competency');
4271 $this->setAdminUser();
4273 $u1 = $dg->create_user();
4274 $u2 = $dg->create_user();
4275 $u3 = $dg->create_user();
4276 $u4 = $dg->create_user();
4277 $c1 = $dg->create_course();
4278 $framework = $lpg->create_framework();
4280 // Create 6 competencies.
4281 $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4282 $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4283 $comp3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4284 $comp4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4285 $comp5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4286 $comp6 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4288 // Link 5 out of 6 to a course.
4289 $lpg->create_course_competency(array('competencyid' => $comp1->get('id'), 'courseid' => $c1->id));
4290 $lpg->create_course_competency(array('competencyid' => $comp2->get('id'), 'courseid' => $c1->id));
4291 $lpg->create_course_competency(array('competencyid' => $comp3->get('id'), 'courseid' => $c1->id));
4292 $lpg->create_course_competency(array('competencyid' => $comp4->get('id'), 'courseid' => $c1->id));
4293 $lpg->create_course_competency(array('competencyid' => $comp5->get('id'), 'courseid' => $c1->id));
4295 // Put all 6 in a template.
4296 $tpl = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_template();
4297 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp1->get('id')));
4298 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp2->get('id')));
4299 $tplc3 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp3->get('id')));
4300 $tplc4 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp4->get('id')));
4301 $tplc5 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp5->get('id')));
4302 $tplc6 = $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $comp6->get('id')));
4304 // Create some plans from the template.
4305 $p1 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u1->id));
4306 $p2 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u2->id));
4307 $p3 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u3->id));
4308 $p4 = $lpg->create_plan(array('templateid' => $tpl->get('id'), 'userid' => $u4->id));
4310 // Rate some competencies.
4311 // User 1.
4312 $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $comp1->get('id'),
4313 'proficiency' => true, 'grade' => 1 ));
4314 $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $comp2->get('id'),
4315 'proficiency' => true, 'grade' => 1 ));
4316 $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $comp3->get('id'),
4317 'proficiency' => true, 'grade' => 1 ));
4318 // User 2.
4319 $lpg->create_user_competency(array('userid' => $u2->id, 'competencyid' => $comp1->get('id'),
4320 'proficiency' => false, 'grade' => 1 ));
4321 $lpg->create_user_competency(array('userid' => $u2->id, 'competencyid' => $comp2->get('id'),
4322 'proficiency' => false, 'grade' => 1 ));
4323 $lpg->create_user_competency(array('userid' => $u2->id, 'competencyid' => $comp3->get('id'),
4324 'proficiency' => false, 'grade' => 1 ));
4325 // User 3.
4326 $lpg->create_user_competency(array('userid' => $u3->id, 'competencyid' => $comp2->get('id'),
4327 'proficiency' => false, 'grade' => 1 ));
4328 $lpg->create_user_competency(array('userid' => $u3->id, 'competencyid' => $comp3->get('id'),
4329 'proficiency' => true, 'grade' => 1 ));
4330 $lpg->create_user_competency(array('userid' => $u3->id, 'competencyid' => $comp4->get('id'),
4331 'proficiency' => false, 'grade' => 1 ));
4332 $lpg->create_user_competency(array('userid' => $u3->id, 'competencyid' => $comp5->get('id'),
4333 'proficiency' => true, 'grade' => 1 ));
4334 // User 4.
4335 $lpg->create_user_competency(array('userid' => $u4->id, 'competencyid' => $comp3->get('id'),
4336 'proficiency' => true, 'grade' => 1 ));
4337 $lpg->create_user_competency(array('userid' => $u4->id, 'competencyid' => $comp5->get('id'),
4338 'proficiency' => true, 'grade' => 1 ));
4340 // Complete 3 out of 4 plans.
4341 api::complete_plan($p1->get('id'));
4342 api::complete_plan($p2->get('id'));
4343 api::complete_plan($p3->get('id'));
4345 // OK we have enough data - lets call some API functions and check for expected results.
4347 $result = api::count_competencies_in_template_with_no_courses($tpl->get('id'));
4348 $this->assertEquals(1, $result);
4350 $result = api::count_plans_for_template($tpl->get('id'));
4351 $this->assertEquals(4, $result);
4353 $result = api::count_plans_for_template($tpl->get('id'), plan::STATUS_COMPLETE);
4354 $this->assertEquals(3, $result);
4356 // This counts the records of competencies in completed plans for all users with a plan from this template.
4357 $result = api::count_user_competency_plans_for_template($tpl->get('id'));
4358 // There should be 3 plans * 6 competencies.
4359 $this->assertEquals(18, $result);
4361 // This counts the records of proficient competencies in completed plans for all users with a plan from this template.
4362 $result = api::count_user_competency_plans_for_template($tpl->get('id'), true);
4363 // There should be 5.
4364 $this->assertEquals(5, $result);
4366 // This counts the records of not proficient competencies in completed plans for all users with a plan from this template.
4367 $result = api::count_user_competency_plans_for_template($tpl->get('id'), false);
4368 // There should be 13.
4369 $this->assertEquals(13, $result);
4371 // This lists the plans based on this template, optionally filtered by status.
4372 $result = api::list_plans_for_template($tpl->get('id'));
4374 $this->assertEquals(4, count($result));
4375 foreach ($result as $one) {
4376 $this->assertInstanceOf('\core_competency\plan', $one);
4378 // This lists the plans based on this template, optionally filtered by status.
4379 $result = api::list_plans_for_template($tpl->get('id'), plan::STATUS_COMPLETE);
4381 $this->assertEquals(3, count($result));
4382 foreach ($result as $one) {
4383 $this->assertInstanceOf('\core_competency\plan', $one);
4384 $this->assertEquals(plan::STATUS_COMPLETE, $one->get('status'));
4387 $result = api::get_least_proficient_competencies_for_template($tpl->get('id'), 0, 2);
4389 // Our times completed counts should look like this:
4390 // - comp1 - 1
4391 // - comp2 - 1
4392 // - comp3 - 2
4393 // - comp4 - 0
4394 // - comp5 - 1
4395 // - comp6 - 0
4397 // And this is a fullstop to make CiBoT happy.
4398 $this->assertEquals(2, count($result));
4399 $leastarray = array($comp4->get('id'), $comp6->get('id'));
4400 foreach ($result as $one) {
4401 $this->assertInstanceOf('\core_competency\competency', $one);
4402 $this->assertContains($one->get('id'), $leastarray);
4406 public function test_is_scale_used_anywhere() {
4407 $this->resetAfterTest();
4408 $dg = $this->getDataGenerator();
4409 $lpg = $dg->get_plugin_generator('core_competency');
4411 $scale1 = $dg->create_scale();
4412 $scale2 = $dg->create_scale();
4413 $scale3 = $dg->create_scale();
4414 $scale4 = $dg->create_scale();
4416 $this->assertFalse(api::is_scale_used_anywhere($scale1->id));
4417 $this->assertFalse(api::is_scale_used_anywhere($scale2->id));
4418 $this->assertFalse(api::is_scale_used_anywhere($scale3->id));
4419 $this->assertFalse(api::is_scale_used_anywhere($scale4->id));
4421 // Using scale 1 in a framework.
4422 $f1 = $lpg->create_framework([
4423 'scaleid' => $scale1->id,
4424 'scaleconfiguration' => json_encode([
4425 ['scaleid' => $scale1->id],
4426 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4429 $this->assertTrue(api::is_scale_used_anywhere($scale1->id));
4430 $this->assertFalse(api::is_scale_used_anywhere($scale2->id));
4431 $this->assertFalse(api::is_scale_used_anywhere($scale3->id));
4432 $this->assertFalse(api::is_scale_used_anywhere($scale4->id));
4434 // Using scale 2 in a competency.
4435 $f2 = $lpg->create_framework();
4436 $c2 = $lpg->create_competency([
4437 'competencyframeworkid' => $f2->get('id'),
4438 'scaleid' => $scale2->id,
4439 'scaleconfiguration' => json_encode([
4440 ['scaleid' => $scale2->id],
4441 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4445 $this->assertTrue(api::is_scale_used_anywhere($scale1->id));
4446 $this->assertTrue(api::is_scale_used_anywhere($scale2->id));
4447 $this->assertFalse(api::is_scale_used_anywhere($scale3->id));
4448 $this->assertFalse(api::is_scale_used_anywhere($scale4->id));
4450 // Using scale 3 in a framework, and scale 4 in a competency of that framework.
4451 $f3 = $lpg->create_framework([
4452 'scaleid' => $scale3->id,
4453 'scaleconfiguration' => json_encode([
4454 ['scaleid' => $scale3->id],
4455 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4458 $c3 = $lpg->create_competency([
4459 'competencyframeworkid' => $f3->get('id'),
4460 'scaleid' => $scale4->id,
4461 'scaleconfiguration' => json_encode([
4462 ['scaleid' => $scale4->id],
4463 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4467 $this->assertTrue(api::is_scale_used_anywhere($scale1->id));
4468 $this->assertTrue(api::is_scale_used_anywhere($scale2->id));
4469 $this->assertTrue(api::is_scale_used_anywhere($scale3->id));
4470 $this->assertTrue(api::is_scale_used_anywhere($scale4->id));
4472 // Multiple occurrences of the same scale (3, and 4).
4473 $f4 = $lpg->create_framework([
4474 'scaleid' => $scale3->id,
4475 'scaleconfiguration' => json_encode([
4476 ['scaleid' => $scale3->id],
4477 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4480 $c4 = $lpg->create_competency([
4481 'competencyframeworkid' => $f3->get('id'),
4482 'scaleid' => $scale4->id,
4483 'scaleconfiguration' => json_encode([
4484 ['scaleid' => $scale4->id],
4485 ['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
4488 $this->assertTrue(api::is_scale_used_anywhere($scale1->id));
4489 $this->assertTrue(api::is_scale_used_anywhere($scale2->id));
4490 $this->assertTrue(api::is_scale_used_anywhere($scale3->id));
4491 $this->assertTrue(api::is_scale_used_anywhere($scale4->id));
4494 public function test_delete_evidence() {
4495 $this->resetAfterTest();
4496 $dg = $this->getDataGenerator();
4497 $ccg = $dg->get_plugin_generator('core_competency');
4499 $u1 = $dg->create_user();
4500 $f1 = $ccg->create_framework();
4501 $comp1 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4502 $uc1 = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $comp1->get('id')]);
4504 $ev1 = $ccg->create_evidence(['usercompetencyid' => $uc1->get('id')]);
4505 $ev2 = $ccg->create_evidence(['usercompetencyid' => $uc1->get('id')]);
4507 $this->setAdminUser($u1);
4509 $this->assertEquals(2, evidence::count_records());
4510 api::delete_evidence($ev1);
4511 $this->assertEquals(1, evidence::count_records());
4512 $this->assertFalse(evidence::record_exists($ev1->get('id')));
4513 $this->assertTrue(evidence::record_exists($ev2->get('id')));
4517 * @expectedException required_capability_exception
4519 public function test_delete_evidence_without_permissions() {
4520 $this->resetAfterTest();
4521 $dg = $this->getDataGenerator();
4522 $ccg = $dg->get_plugin_generator('core_competency');
4524 $u1 = $dg->create_user();
4525 $f1 = $ccg->create_framework();
4526 $comp1 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4527 $uc1 = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $comp1->get('id')]);
4528 $ev1 = $ccg->create_evidence(['usercompetencyid' => $uc1->get('id')]);
4530 $this->setUser($u1);
4532 api::delete_evidence($ev1);
4535 public function test_list_plans_to_review() {
4536 $dg = $this->getDataGenerator();
4537 $this->resetAfterTest();
4538 $ccg = $dg->get_plugin_generator('core_competency');
4539 $sysctx = context_system::instance();
4540 $this->setAdminUser();
4542 $reviewer = $dg->create_user();
4543 $roleallow = $dg->create_role();
4544 $roleprohibit = $dg->create_role();
4545 assign_capability('moodle/competency:planreview', CAP_ALLOW, $roleallow, $sysctx->id);
4546 assign_capability('moodle/competency:planreview', CAP_PROHIBIT, $roleprohibit, $sysctx->id);
4547 role_assign($roleallow, $reviewer->id, $sysctx->id);
4548 accesslib_clear_all_caches_for_unit_testing();
4550 $u1 = $dg->create_user();
4551 $u2 = $dg->create_user();
4552 $f1 = $ccg->create_framework();
4553 $comp1 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4554 $p1a = $ccg->create_plan(['userid' => $u1->id, 'status' => plan::STATUS_WAITING_FOR_REVIEW]);
4555 $p1b = $ccg->create_plan(['userid' => $u1->id, 'status' => plan::STATUS_IN_REVIEW, 'reviewerid' => $reviewer->id]);
4556 $p1c = $ccg->create_plan(['userid' => $u1->id, 'status' => plan::STATUS_DRAFT]);
4557 $p2a = $ccg->create_plan(['userid' => $u2->id, 'status' => plan::STATUS_WAITING_FOR_REVIEW]);
4558 $p2b = $ccg->create_plan(['userid' => $u2->id, 'status' => plan::STATUS_IN_REVIEW]);
4559 $p2c = $ccg->create_plan(['userid' => $u2->id, 'status' => plan::STATUS_ACTIVE]);
4560 $p2d = $ccg->create_plan(['userid' => $u2->id, 'status' => plan::STATUS_ACTIVE]);
4561 api::complete_plan($p2d);
4563 // The reviewer can review all plans waiting for review, or in review where they are the reviewer.
4564 $this->setUser($reviewer);
4565 $result = api::list_plans_to_review();
4566 $this->assertEquals(3, $result['count']);
4567 $this->assertEquals($p1a->get('id'), $result['plans'][0]->plan->get('id'));
4568 $this->assertEquals($p1b->get('id'), $result['plans'][1]->plan->get('id'));
4569 $this->assertEquals($p2a->get('id'), $result['plans'][2]->plan->get('id'));
4571 // The reviewer cannot view the plans when they do not have the permission in the user's context.
4572 role_assign($roleprohibit, $reviewer->id, context_user::instance($u2->id)->id);
4573 accesslib_clear_all_caches_for_unit_testing();
4574 $result = api::list_plans_to_review();
4575 $this->assertEquals(2, $result['count']);
4576 $this->assertEquals($p1a->get('id'), $result['plans'][0]->plan->get('id'));
4577 $this->assertEquals($p1b->get('id'), $result['plans'][1]->plan->get('id'));
4580 public function test_list_user_competencies_to_review() {
4581 global $CFG;
4582 require_once($CFG->dirroot . '/user/lib.php');
4584 $dg = $this->getDataGenerator();
4585 $this->resetAfterTest();
4586 $ccg = $dg->get_plugin_generator('core_competency');
4587 $sysctx = context_system::instance();
4588 $this->setAdminUser();
4590 $reviewer = $dg->create_user();
4591 $roleallow = $dg->create_role();
4592 $roleprohibit = $dg->create_role();
4593 assign_capability('moodle/competency:usercompetencyreview', CAP_ALLOW, $roleallow, $sysctx->id);
4594 assign_capability('moodle/competency:usercompetencyreview', CAP_PROHIBIT, $roleprohibit, $sysctx->id);
4595 role_assign($roleallow, $reviewer->id, $sysctx->id);
4596 accesslib_clear_all_caches_for_unit_testing();
4598 $u1 = $dg->create_user();
4599 $u2 = $dg->create_user();
4600 $u3 = $dg->create_user();
4601 $f1 = $ccg->create_framework();
4602 $c1 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4603 $c2 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4604 $c3 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4605 $c4 = $ccg->create_competency(['competencyframeworkid' => $f1->get('id')]);
4606 $uc1a = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c1->get('id'),
4607 'status' => user_competency::STATUS_IDLE]);
4608 $uc1b = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c2->get('id'),
4609 'status' => user_competency::STATUS_WAITING_FOR_REVIEW]);
4610 $uc1c = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c3->get('id'),
4611 'status' => user_competency::STATUS_IN_REVIEW, 'reviewerid' => $reviewer->id]);
4612 $uc2a = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c1->get('id'),
4613 'status' => user_competency::STATUS_WAITING_FOR_REVIEW]);
4614 $uc2b = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c2->get('id'),
4615 'status' => user_competency::STATUS_IDLE]);
4616 $uc2c = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c3->get('id'),
4617 'status' => user_competency::STATUS_IN_REVIEW]);
4618 $uc3a = $ccg->create_user_competency(['userid' => $u3->id, 'competencyid' => $c4->get('id'),
4619 'status' => user_competency::STATUS_WAITING_FOR_REVIEW]);
4621 // The reviewer can review all plans waiting for review, or in review where they are the reviewer.
4622 $this->setUser($reviewer);
4623 $result = api::list_user_competencies_to_review();
4624 $this->assertEquals(4, $result['count']);
4625 $this->assertEquals($uc2a->get('id'), $result['competencies'][0]->usercompetency->get('id'));
4626 $this->assertEquals($uc1b->get('id'), $result['competencies'][1]->usercompetency->get('id'));
4627 $this->assertEquals($uc1c->get('id'), $result['competencies'][2]->usercompetency->get('id'));
4628 $this->assertEquals($uc3a->get('id'), $result['competencies'][3]->usercompetency->get('id'));
4630 // Now, let's delete user 3.
4631 // It should not be listed on user competencies to review any more.
4632 user_delete_user($u3);
4633 $result = api::list_user_competencies_to_review();
4634 $this->assertEquals(3, $result['count']);
4636 // The reviewer cannot view the plans when they do not have the permission in the user's context.
4637 role_assign($roleprohibit, $reviewer->id, context_user::instance($u2->id)->id);
4638 accesslib_clear_all_caches_for_unit_testing();
4639 $result = api::list_user_competencies_to_review();
4640 $this->assertEquals(2, $result['count']);
4641 $this->assertEquals($uc1b->get('id'), $result['competencies'][0]->usercompetency->get('id'));
4642 $this->assertEquals($uc1c->get('id'), $result['competencies'][1]->usercompetency->get('id'));
4646 * Test we can get all of a users plans with a competency.
4648 public function test_list_plans_with_competency() {
4649 $this->resetAfterTest(true);
4650 $this->setAdminUser();
4651 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
4653 $u1 = $this->getDataGenerator()->create_user();
4654 $tpl = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_template();
4656 // Create a framework and assign competencies.
4657 $framework = $lpg->create_framework();
4658 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
4660 // Create two plans and assign the competency to each.
4661 $plan1 = $lpg->create_plan(array('userid' => $u1->id));
4662 $plan2 = $lpg->create_plan(array('userid' => $u1->id));
4664 $lpg->create_plan_competency(array('planid' => $plan1->get('id'), 'competencyid' => $c1->get('id')));
4665 $lpg->create_plan_competency(array('planid' => $plan2->get('id'), 'competencyid' => $c1->get('id')));
4667 // Create one more plan without the competency.
4668 $plan3 = $lpg->create_plan(array('userid' => $u1->id));
4670 $plans = api::list_plans_with_competency($u1->id, $c1);
4672 $this->assertEquals(2, count($plans));
4674 $this->assertEquals(reset($plans)->get('id'), $plan1->get('id'));
4675 $this->assertEquals(end($plans)->get('id'), $plan2->get('id'));