2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
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();
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;
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');
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');
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 public function test_update_template() {
171 $cat = $this->getDataGenerator()->create_category();
172 $this->resetAfterTest(true);
173 $this->setAdminUser();
175 $syscontext = context_system::instance();
176 $template = api::create_template((object) array('shortname' => 'testing', 'contextid' => $syscontext->id));
178 $this->assertEquals('testing', $template->get_shortname());
179 $this->assertEquals($syscontext->id, $template->get_contextid());
182 api::update_template((object) array('id' => $template->get_id(), 'shortname' => 'success'));
183 $template = api::read_template($template->get_id());
184 $this->assertEquals('success', $template->get_shortname());
186 // Trying to change the context.
187 $this->setExpectedException('coding_exception');
188 api::update_template((object) array('id' => $template->get_id(), 'contextid' => context_coursecat::instance($cat->id)));
192 * Test listing framework with order param.
194 public function test_list_frameworks() {
195 $this->resetAfterTest(true);
196 $this->setAdminUser();
197 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
199 // Create a list of frameworks.
200 $framework1 = $lpg->create_framework(array(
201 'shortname' => 'shortname_alpha',
202 'idnumber' => 'idnumber_cinnamon',
203 'description' => 'description',
204 'descriptionformat' => FORMAT_HTML,
206 'contextid' => context_system::instance()->id
209 $framework2 = $lpg->create_framework(array(
210 'shortname' => 'shortname_beetroot',
211 'idnumber' => 'idnumber_apple',
212 'description' => 'description',
213 'descriptionformat' => FORMAT_HTML,
215 'contextid' => context_system::instance()->id
218 $framework3 = $lpg->create_framework(array(
219 'shortname' => 'shortname_crisps',
220 'idnumber' => 'idnumber_beer',
221 'description' => 'description',
222 'descriptionformat' => FORMAT_HTML,
224 'contextid' => context_system::instance()->id
227 // Get frameworks list order by shortname desc.
228 $result = api::list_frameworks('shortname', 'DESC', null, 3, context_system::instance());
230 $f = (object) array_shift($result);
231 $this->assertEquals($framework3->get_id(), $f->get_id());
232 $f = (object) array_shift($result);
233 $this->assertEquals($framework2->get_id(), $f->get_id());
234 $f = (object) array_shift($result);
235 $this->assertEquals($framework1->get_id(), $f->get_id());
237 // Get frameworks list order by idnumber asc.
238 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance());
240 $f = (object) array_shift($result);
241 $this->assertEquals($framework2->get_id(), $f->get_id());
242 $f = (object) array_shift($result);
243 $this->assertEquals($framework3->get_id(), $f->get_id());
244 $f = (object) array_shift($result);
245 $this->assertEquals($framework1->get_id(), $f->get_id());
247 // Repeat excluding the non-visible ones.
248 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', true);
249 $this->assertCount(2, $result);
250 $f = (object) array_shift($result);
251 $this->assertEquals($framework2->get_id(), $f->get_id());
252 $f = (object) array_shift($result);
253 $this->assertEquals($framework1->get_id(), $f->get_id());
255 // Search by query string, trying match on shortname.
256 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'crisp');
257 $this->assertCount(1, $result);
258 $f = (object) array_shift($result);
259 $this->assertEquals($framework3->get_id(), $f->get_id());
261 // Search by query string, trying match on shortname, but hidden.
262 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', true, 'crisp');
263 $this->assertCount(0, $result);
265 // Search by query string, trying match on ID number.
266 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'apple');
267 $this->assertCount(1, $result);
268 $f = (object) array_shift($result);
269 $this->assertEquals($framework2->get_id(), $f->get_id());
271 // Search by query string, trying match on both.
272 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance(), 'self', false, 'bee');
273 $this->assertCount(2, $result);
274 $f = (object) array_shift($result);
275 $this->assertEquals($framework2->get_id(), $f->get_id());
276 $f = (object) array_shift($result);
277 $this->assertEquals($framework3->get_id(), $f->get_id());
281 * Test duplicate a framework.
283 public function test_duplicate_framework() {
284 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
285 $this->resetAfterTest(true);
286 $this->setAdminUser();
288 $syscontext = context_system::instance();
290 'shortname' => 'shortname_a',
291 'idnumber' => 'idnumber_c',
292 'description' => 'description',
293 'descriptionformat' => FORMAT_HTML,
295 'contextid' => $syscontext->id
297 $framework = $lpg->create_framework($params);
298 $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
299 $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
300 $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
301 $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
302 $competency41 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
303 'parentid' => $competency4->get_id())
305 $competency42 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
306 'parentid' => $competency4->get_id())
308 $competencyidnumbers = array($competency1->get_idnumber(),
309 $competency2->get_idnumber(),
310 $competency3->get_idnumber(),
311 $competency4->get_idnumber(),
312 $competency41->get_idnumber(),
313 $competency42->get_idnumber()
316 $config = json_encode(array(
317 'base' => array('points' => 4),
318 'competencies' => array(
319 array('id' => $competency41->get_id(), 'points' => 3, 'required' => 0),
320 array('id' => $competency42->get_id(), 'points' => 2, 'required' => 1),
323 $competency4->set_ruletype('core_competency\competency_rule_points');
324 $competency4->set_ruleoutcome(\core_competency\competency::OUTCOME_EVIDENCE);
325 $competency4->set_ruleconfig($config);
326 $competency4->update();
328 api::add_related_competency($competency1->get_id(), $competency2->get_id());
329 api::add_related_competency($competency3->get_id(), $competency4->get_id());
331 $frameworkduplicated1 = api::duplicate_framework($framework->get_id());
332 $frameworkduplicated2 = api::duplicate_framework($framework->get_id());
334 $this->assertEquals($framework->get_idnumber().'_1', $frameworkduplicated1->get_idnumber());
335 $this->assertEquals($framework->get_idnumber().'_2', $frameworkduplicated2->get_idnumber());
337 $competenciesfr1 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated1->get_id()));
338 $competenciesfr2 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated2->get_id()));
340 $competencyidsfr1 = array();
341 $competencyidsfr2 = array();
343 foreach ($competenciesfr1 as $cmp) {
344 $competencyidsfr1[] = $cmp->get_idnumber();
346 foreach ($competenciesfr2 as $cmp) {
347 $competencyidsfr2[] = $cmp->get_idnumber();
350 $this->assertEmpty(array_diff($competencyidsfr1, $competencyidnumbers));
351 $this->assertEmpty(array_diff($competencyidsfr2, $competencyidnumbers));
352 $this->assertCount(6, $competenciesfr1);
353 $this->assertCount(6, $competenciesfr2);
355 // Test the related competencies.
356 reset($competenciesfr1);
357 $compduplicated1 = current($competenciesfr1);
358 $relatedcompetencies = $compduplicated1->get_related_competencies();
359 $comprelated = current($relatedcompetencies);
360 $this->assertEquals($comprelated->get_idnumber(), $competency2->get_idnumber());
362 // Check if config rule have been ported correctly.
363 $competency4duplicated = competency::get_record(array(
364 'idnumber' => $competency4->get_idnumber(),
365 'competencyframeworkid' => $frameworkduplicated2->get_id()
367 $configduplicated = json_decode($competency4duplicated->get_ruleconfig(), true);
368 $configorigin = json_decode($config, true);
369 // Check that the 2 config have the same base.
370 $this->assertEquals($configorigin['base'], $configduplicated['base']);
371 $this->assertEquals(count($configorigin['competencies']), count($configduplicated['competencies']));
372 $competencyidsrules = array();
373 foreach ($configduplicated['competencies'] as $key => $value) {
374 // Check that the only difference between the 2 config is id competency.
375 $this->assertEquals(1, count(array_diff($value, $configorigin['competencies'][$key])));
376 $competencyidsrules[] = $value['id'];
378 $this->assertTrue($competency4duplicated->is_parent_of($competencyidsrules));
380 // Test duplicate an empty framework.
381 $emptyfrm = $lpg->create_framework();
382 $emptyfrmduplicated = api::duplicate_framework($emptyfrm->get_id());
383 $this->assertEquals($emptyfrm->get_idnumber().'_1', $emptyfrmduplicated->get_idnumber());
384 $nbcomp = api::count_competencies(array('competencyframeworkid' => $emptyfrmduplicated->get_id()));
385 $this->assertEquals(0, $nbcomp);
392 public function test_update_plan() {
393 $this->resetAfterTest(true);
394 $dg = $this->getDataGenerator();
395 $usermanageowndraft = $dg->create_user();
396 $usermanageown = $dg->create_user();
397 $usermanagedraft = $dg->create_user();
398 $usermanage = $dg->create_user();
400 $syscontext = context_system::instance();
402 // Creating specific roles.
403 $manageowndraftrole = $dg->create_role(array(
404 'name' => 'User manage own draft',
405 'shortname' => 'manage-own-draft'
407 $manageownrole = $dg->create_role(array(
408 'name' => 'User manage own',
409 'shortname' => 'manage-own'
411 $managedraftrole = $dg->create_role(array(
412 'name' => 'User manage draft',
413 'shortname' => 'manage-draft'
415 $managerole = $dg->create_role(array(
416 'name' => 'User manage',
417 'shortname' => 'manage'
420 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
421 assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
423 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
424 assign_capability('moodle/competency:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
426 assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
427 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
429 assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
430 assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
432 $dg->role_assign($manageowndraftrole, $usermanageowndraft->id, $syscontext->id);
433 $dg->role_assign($manageownrole, $usermanageown->id, $syscontext->id);
434 $dg->role_assign($managedraftrole, $usermanagedraft->id, $syscontext->id);
435 $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
437 // Create first learning plan with user create draft.
438 $this->setUser($usermanageowndraft);
440 'name' => 'plan own draft',
441 'description' => 'plan own draft',
442 'userid' => $usermanageowndraft->id
444 $plan = api::create_plan((object)$plan);
445 $record = $plan->to_record();
446 $record->name = 'plan own draft modified';
448 // Check if user create draft can edit the plan name.
449 $plan = api::update_plan($record);
450 $this->assertInstanceOf('\core_competency\plan', $plan);
452 // The status cannot be changed in this method.
453 $record->status = \core_competency\plan::STATUS_ACTIVE;
455 $plan = api::update_plan($record);
456 $this->fail('Updating the status is not allowed.');
457 } catch (coding_exception $e) {
458 $this->assertRegExp('/To change the status of a plan use the appropriate methods./', $e->getMessage());
461 // Test when user with manage own plan capability try to edit other user plan.
462 $record->status = \core_competency\plan::STATUS_DRAFT;
463 $record->name = 'plan create draft modified 2';
464 $this->setUser($usermanageown);
466 $plan = api::update_plan($record);
467 $this->fail('User with manage own plan capability can only edit his own plan.');
468 } catch (required_capability_exception $e) {
469 $this->assertTrue(true);
472 // User with manage plan capability cannot edit the other user plans with status draft.
473 $this->setUser($usermanage);
474 $record->name = 'plan create draft modified 3';
476 $plan = api::update_plan($record);
477 $this->fail('User with manage plan capability cannot edit the other user plans with status draft');
478 } catch (required_capability_exception $e) {
479 $this->assertTrue(true);
482 // User with manage draft capability can edit other user's learning plan if the status is draft.
483 $this->setUser($usermanagedraft);
484 $record->status = \core_competency\plan::STATUS_DRAFT;
485 $record->name = 'plan manage draft modified 3';
486 $plan = api::update_plan($record);
487 $this->assertInstanceOf('\core_competency\plan', $plan);
489 // User with manage plan capability can create/edit learning plan if status is active/complete.
490 $this->setUser($usermanage);
492 'name' => 'plan create',
493 'description' => 'plan create',
494 'userid' => $usermanage->id,
495 'status' => \core_competency\plan::STATUS_ACTIVE
497 $plan = api::create_plan((object)$plan);
499 // Silently transition to complete status to avoid errors about transitioning to complete.
500 $plan->set_status(\core_competency\plan::STATUS_COMPLETE);
503 $record = $plan->to_record();
504 $record->name = 'plan create own modified';
506 api::update_plan($record);
507 $this->fail('Completed plan can not be edited');
508 } catch (coding_exception $e) {
509 $this->assertTrue(true);
513 public function test_create_plan_from_template() {
514 $this->resetAfterTest(true);
515 $this->setAdminUser();
517 $u1 = $this->getDataGenerator()->create_user();
518 $tpl = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_template();
520 // Creating a new plan.
521 $plan = api::create_plan_from_template($tpl, $u1->id);
522 $record = $plan->to_record();
523 $this->assertInstanceOf('\core_competency\plan', $plan);
524 $this->assertTrue(\core_competency\plan::record_exists($plan->get_id()));
525 $this->assertEquals($tpl->get_id(), $plan->get_templateid());
526 $this->assertEquals($u1->id, $plan->get_userid());
527 $this->assertTrue($plan->is_based_on_template());
529 // Creating a plan that already exists.
530 $plan = api::create_plan_from_template($tpl, $u1->id);
531 $this->assertFalse($plan);
533 // Check that api::create_plan cannot be used.
534 $this->setExpectedException('coding_exception');
536 $plan = api::create_plan($record);
539 public function test_update_plan_based_on_template() {
540 $this->resetAfterTest(true);
541 $dg = $this->getDataGenerator();
542 $lpg = $dg->get_plugin_generator('core_competency');
543 $u1 = $dg->create_user();
544 $u2 = $dg->create_user();
546 $this->setAdminUser();
547 $tpl1 = $lpg->create_template();
548 $tpl2 = $lpg->create_template();
549 $up1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id()));
550 $up2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => null));
553 // Trying to remove the template dependency.
554 $record = $up1->to_record();
555 $record->templateid = null;
556 api::update_plan($record);
557 $this->fail('A plan cannot be unlinked using api::update_plan()');
558 } catch (coding_exception $e) {
563 // Trying to switch to another template.
564 $record = $up1->to_record();
565 $record->templateid = $tpl2->get_id();
566 api::update_plan($record);
567 $this->fail('A plan cannot be moved to another template.');
568 } catch (coding_exception $e) {
573 // Trying to switch to using a template.
574 $record = $up2->to_record();
575 $record->templateid = $tpl1->get_id();
576 api::update_plan($record);
577 $this->fail('A plan cannot be update to use a template.');
578 } catch (coding_exception $e) {
583 public function test_unlink_plan_from_template() {
584 $this->resetAfterTest(true);
585 $dg = $this->getDataGenerator();
586 $lpg = $dg->get_plugin_generator('core_competency');
587 $u1 = $dg->create_user();
588 $u2 = $dg->create_user();
590 $this->setAdminUser();
591 $f1 = $lpg->create_framework();
592 $f2 = $lpg->create_framework();
593 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
594 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
595 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
597 $tpl1 = $lpg->create_template();
598 $tpl2 = $lpg->create_template();
600 $tplc1a = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1a->get_id(),
602 $tplc1b = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1b->get_id(),
604 $tplc2a = $lpg->create_template_competency(array('templateid' => $tpl2->get_id(), 'competencyid' => $c2a->get_id()));
606 $plan1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_ACTIVE));
607 $plan2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => $tpl2->get_id()));
608 $plan3 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_COMPLETE));
610 // Check that we have what we expect at this stage.
611 $this->assertEquals(2, \core_competency\template_competency::count_records(array('templateid' => $tpl1->get_id())));
612 $this->assertEquals(1, \core_competency\template_competency::count_records(array('templateid' => $tpl2->get_id())));
613 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan1->get_id())));
614 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan2->get_id())));
615 $this->assertTrue($plan1->is_based_on_template());
616 $this->assertTrue($plan2->is_based_on_template());
619 $tpl1comps = \core_competency\template_competency::list_competencies($tpl1->get_id(), true);
620 $tpl2comps = \core_competency\template_competency::list_competencies($tpl2->get_id(), true);
622 api::unlink_plan_from_template($plan1);
626 $this->assertCount(2, $tpl1comps);
627 $this->assertCount(1, $tpl2comps);
628 $this->assertEquals(2, \core_competency\template_competency::count_records(array('templateid' => $tpl1->get_id())));
629 $this->assertEquals(1, \core_competency\template_competency::count_records(array('templateid' => $tpl2->get_id())));
630 $this->assertEquals(2, \core_competency\plan_competency::count_records(array('planid' => $plan1->get_id())));
631 $this->assertEquals(0, \core_competency\plan_competency::count_records(array('planid' => $plan2->get_id())));
632 $this->assertFalse($plan1->is_based_on_template());
633 $this->assertEquals($tpl1->get_id(), $plan1->get_origtemplateid());
634 $this->assertTrue($plan2->is_based_on_template());
635 $this->assertEquals(null, $plan2->get_origtemplateid());
637 // Check we can unlink draft plan.
639 api::unlink_plan_from_template($plan2);
640 } catch (coding_exception $e) {
641 $this->fail('Fail to unlink draft plan.');
644 // Check we can not unlink completed plan.
646 api::unlink_plan_from_template($plan3);
647 $this->fail('We can not unlink completed plan.');
648 } catch (coding_exception $e) {
652 // Even the order remains.
653 $plan1comps = \core_competency\plan_competency::list_competencies($plan1->get_id());
654 $before = reset($tpl1comps);
655 $after = reset($plan1comps);
656 $this->assertEquals($before->get_id(), $after->get_id());
657 $this->assertEquals($before->get_sortorder(), $after->get_sortorder());
658 $before = next($tpl1comps);
659 $after = next($plan1comps);
660 $this->assertEquals($before->get_id(), $after->get_id());
661 $this->assertEquals($before->get_sortorder(), $after->get_sortorder());
664 public function test_update_template_updates_plans() {
665 $this->resetAfterTest(true);
666 $this->setAdminUser();
668 $dg = $this->getDataGenerator();
669 $u1 = $dg->create_user();
670 $u2 = $dg->create_user();
671 $lpg = $dg->get_plugin_generator('core_competency');
672 $tpl1 = $lpg->create_template();
673 $tpl2 = $lpg->create_template();
675 // Create plans with data not matching templates.
677 $plan1 = $lpg->create_plan(array('templateid' => $tpl1->get_id(), 'userid' => $u1->id,
678 'name' => 'Not good name', 'duedate' => $time + 3600, 'description' => 'Ahah', 'descriptionformat' => FORMAT_MARKDOWN));
679 $plan2 = $lpg->create_plan(array('templateid' => $tpl1->get_id(), 'userid' => $u2->id,
680 'name' => 'Not right name', 'duedate' => $time + 3601, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
681 $plan3 = $lpg->create_plan(array('templateid' => $tpl2->get_id(), 'userid' => $u1->id,
682 'name' => 'Not sweet name', 'duedate' => $time + 3602, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
684 // Prepare our expectations.
689 $this->assertEquals($tpl1->get_id(), $plan1->get_templateid());
690 $this->assertEquals($tpl1->get_id(), $plan2->get_templateid());
691 $this->assertEquals($tpl2->get_id(), $plan3->get_templateid());
692 $this->assertNotEquals($tpl1->get_shortname(), $plan1->get_name());
693 $this->assertNotEquals($tpl1->get_shortname(), $plan2->get_name());
694 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
695 $this->assertNotEquals($tpl1->get_description(), $plan1->get_description());
696 $this->assertNotEquals($tpl1->get_description(), $plan2->get_description());
697 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
698 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
699 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
700 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
701 $this->assertNotEquals($tpl1->get_duedate(), $plan1->get_duedate());
702 $this->assertNotEquals($tpl1->get_duedate(), $plan2->get_duedate());
703 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
705 // Update the template without changing critical fields does not update the plans.
706 $data = $tpl1->to_record();
708 api::update_template($data);
709 $this->assertNotEquals($tpl1->get_shortname(), $plan1->get_name());
710 $this->assertNotEquals($tpl1->get_shortname(), $plan2->get_name());
711 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
712 $this->assertNotEquals($tpl1->get_description(), $plan1->get_description());
713 $this->assertNotEquals($tpl1->get_description(), $plan2->get_description());
714 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
715 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
716 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
717 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
718 $this->assertNotEquals($tpl1->get_duedate(), $plan1->get_duedate());
719 $this->assertNotEquals($tpl1->get_duedate(), $plan2->get_duedate());
720 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
722 // Now really update the template.
723 $data = $tpl1->to_record();
724 $data->shortname = 'Awesome!';
725 $data->description = 'This is too awesome!';
726 $data->descriptionformat = FORMAT_HTML;
727 $data->duedate = $time + 200;
728 api::update_template($data);
731 // Now confirm that the right plans were updated.
736 $this->assertEquals($tpl1->get_id(), $plan1->get_templateid());
737 $this->assertEquals($tpl1->get_id(), $plan2->get_templateid());
738 $this->assertEquals($tpl2->get_id(), $plan3->get_templateid());
740 $this->assertEquals($tpl1->get_shortname(), $plan1->get_name());
741 $this->assertEquals($tpl1->get_shortname(), $plan2->get_name());
742 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
743 $this->assertEquals($tpl1->get_description(), $plan1->get_description());
744 $this->assertEquals($tpl1->get_description(), $plan2->get_description());
745 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
746 $this->assertEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
747 $this->assertEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
748 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
749 $this->assertEquals($tpl1->get_duedate(), $plan1->get_duedate());
750 $this->assertEquals($tpl1->get_duedate(), $plan2->get_duedate());
751 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
755 * Test that the method to complete a plan.
757 public function test_complete_plan() {
760 $this->resetAfterTest(true);
761 $this->setAdminUser();
762 $dg = $this->getDataGenerator();
763 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
764 $user = $dg->create_user();
766 // Create a framework and assign competencies.
767 $framework = $lpg->create_framework();
768 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
769 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
770 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
771 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
773 // Create two plans and assign competencies.
774 $plan = $lpg->create_plan(array('userid' => $user->id));
775 $otherplan = $lpg->create_plan(array('userid' => $user->id));
777 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c1->get_id()));
778 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c2->get_id()));
779 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c3->get_id()));
780 $lpg->create_plan_competency(array('planid' => $otherplan->get_id(), 'competencyid' => $c1->get_id()));
783 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
784 'proficiency' => true, 'grade' => 1 )),
785 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
786 'proficiency' => false, 'grade' => 2 ))
789 $this->assertEquals(2, \core_competency\user_competency::count_records());
790 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
792 // Change status of the plan to complete.
793 api::complete_plan($plan);
795 // Check that user competencies are now in user_competency_plan objects and still in user_competency.
796 $this->assertEquals(2, \core_competency\user_competency::count_records());
797 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
799 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
801 $this->assertEquals($uclist[0]->get_userid(), $usercompetenciesplan[0]->get_userid());
802 $this->assertEquals($uclist[0]->get_competencyid(), $usercompetenciesplan[0]->get_competencyid());
803 $this->assertEquals($uclist[0]->get_proficiency(), (bool) $usercompetenciesplan[0]->get_proficiency());
804 $this->assertEquals($uclist[0]->get_grade(), $usercompetenciesplan[0]->get_grade());
805 $this->assertEquals($plan->get_id(), $usercompetenciesplan[0]->get_planid());
807 $this->assertEquals($uclist[1]->get_userid(), $usercompetenciesplan[1]->get_userid());
808 $this->assertEquals($uclist[1]->get_competencyid(), $usercompetenciesplan[1]->get_competencyid());
809 $this->assertEquals($uclist[1]->get_proficiency(), (bool) $usercompetenciesplan[1]->get_proficiency());
810 $this->assertEquals($uclist[1]->get_grade(), $usercompetenciesplan[1]->get_grade());
811 $this->assertEquals($plan->get_id(), $usercompetenciesplan[1]->get_planid());
813 $this->assertEquals($user->id, $usercompetenciesplan[2]->get_userid());
814 $this->assertEquals($c3->get_id(), $usercompetenciesplan[2]->get_competencyid());
815 $this->assertNull($usercompetenciesplan[2]->get_proficiency());
816 $this->assertNull($usercompetenciesplan[2]->get_grade());
817 $this->assertEquals($plan->get_id(), $usercompetenciesplan[2]->get_planid());
819 // Check we can not add competency to completed plan.
821 api::add_competency_to_plan($plan->get_id(), $c4->get_id());
822 $this->fail('We can not add competency to completed plan.');
823 } catch (coding_exception $e) {
827 // Check we can not remove competency to completed plan.
829 api::remove_competency_from_plan($plan->get_id(), $c3->get_id());
830 $this->fail('We can not remove competency to completed plan.');
831 } catch (coding_exception $e) {
835 // Completing a plan that is completed throws an exception.
836 $this->setExpectedException('coding_exception');
837 api::complete_plan($plan);
841 * Set-up the workflow data (review, active, ...).
845 protected function setup_workflow_data() {
846 $this->resetAfterTest();
848 $dg = $this->getDataGenerator();
849 $user = $dg->create_user();
850 $reviewer = $dg->create_user();
851 $otheruser = $dg->create_user();
853 $syscontext = context_system::instance();
854 $userrole = $dg->create_role();
855 $reviewerrole = $dg->create_role();
856 $otheruserrole = $dg->create_role();
858 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $userrole, $syscontext->id);
859 assign_capability('moodle/competency:planmanage', CAP_ALLOW, $reviewerrole, $syscontext->id);
860 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $reviewerrole, $syscontext->id);
861 $dg->role_assign($userrole, $user->id, $syscontext->id);
862 $dg->role_assign($reviewerrole, $reviewer->id, $syscontext->id);
863 accesslib_clear_all_caches_for_unit_testing();
865 $lpg = $dg->get_plugin_generator('core_competency');
866 $tpl = $lpg->create_template();
867 $plan = $lpg->create_plan(array('userid' => $user->id));
868 $tplplan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tpl->get_id()));
874 'reviewer' => $reviewer,
875 'otheruser' => $otheruser,
877 'tplplan' => $tplplan,
882 * Testing requesting the review of a plan.
884 public function test_plan_request_review() {
885 $data = $this->setup_workflow_data();
888 $user = $data['user'];
889 $reviewer = $data['reviewer'];
890 $otheruser = $data['otheruser'];
891 $plan = $data['plan'];
892 $tplplan = $data['tplplan'];
894 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
895 $this->assertEquals(plan::STATUS_DRAFT, $tplplan->get_status());
897 // Foreign user cannot do anything.
898 $this->setUser($otheruser);
900 api::plan_request_review($plan);
901 $this->fail('The user can not read the plan.');
902 } catch (required_capability_exception $e) {
903 $this->assertEquals('nopermissions', $e->errorcode);
906 // Can not change a plan based on a template.
907 $this->setUser($user);
909 api::plan_request_review($tplplan);
910 $this->fail('The plan is based on a template.');
911 } catch (coding_exception $e) {
912 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
915 // Can not send for review when not draft.
916 $this->setUser($user);
917 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
919 api::plan_request_review($plan);
920 $this->fail('The plan cannot be sent for review at this stage.');
921 } catch (coding_exception $e) {
922 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
925 // Can not send for review when not draft.
926 $this->setUser($user);
927 $plan->set_status(plan::STATUS_ACTIVE);
929 api::plan_request_review($plan);
930 $this->fail('The plan cannot be sent for review at this stage.');
931 } catch (coding_exception $e) {
932 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
935 // Can not send for review when not draft.
936 $this->setUser($user);
937 $plan->set_status(plan::STATUS_IN_REVIEW);
939 api::plan_request_review($plan);
940 $this->fail('The plan cannot be sent for review at this stage.');
941 } catch (coding_exception $e) {
942 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
945 // Can not send for review when not draft.
946 $this->setUser($user);
947 $plan->set_status(plan::STATUS_COMPLETE);
949 api::plan_request_review($plan);
950 $this->fail('The plan cannot be sent for review at this stage.');
951 } catch (coding_exception $e) {
952 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
955 // Sending for review as a reviewer.
956 $this->setUser($reviewer);
957 $plan->set_status(plan::STATUS_DRAFT);
959 api::plan_request_review($plan);
960 $this->fail('The user can not request a review.');
961 } catch (required_capability_exception $e) {
962 $this->assertEquals('nopermissions', $e->errorcode);
965 // Sending for review.
966 $this->setUser($user);
967 api::plan_request_review($plan);
969 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
971 // Sending for review by ID.
972 $plan->set_status(plan::STATUS_DRAFT);
974 api::plan_request_review($plan->get_id());
976 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
980 * Testing cancelling the review request.
982 public function test_plan_cancel_review_request() {
983 $data = $this->setup_workflow_data();
986 $user = $data['user'];
987 $reviewer = $data['reviewer'];
988 $otheruser = $data['otheruser'];
989 $plan = $data['plan'];
990 $tplplan = $data['tplplan'];
992 // Set waiting for review.
993 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
995 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
998 // Foreign user cannot do anything.
999 $this->setUser($otheruser);
1001 api::plan_cancel_review_request($plan);
1002 $this->fail('The user can not read the plan.');
1003 } catch (required_capability_exception $e) {
1004 $this->assertEquals('nopermissions', $e->errorcode);
1007 // Can not change a plan based on a template.
1008 $this->setUser($user);
1010 api::plan_cancel_review_request($tplplan);
1011 $this->fail('The plan is based on a template.');
1012 } catch (coding_exception $e) {
1013 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1016 // Can not cancel review request when not waiting for review.
1017 $this->setUser($user);
1018 $plan->set_status(plan::STATUS_DRAFT);
1020 api::plan_cancel_review_request($plan);
1021 $this->fail('The plan cannot be sent for review at this stage.');
1022 } catch (coding_exception $e) {
1023 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1026 // Can not cancel review request when not waiting for review.
1027 $this->setUser($user);
1028 $plan->set_status(plan::STATUS_IN_REVIEW);
1030 api::plan_cancel_review_request($plan);
1031 $this->fail('The plan review cannot be cancelled at this stage.');
1032 } catch (coding_exception $e) {
1033 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1036 // Can not cancel review request when not waiting for review.
1037 $this->setUser($user);
1038 $plan->set_status(plan::STATUS_ACTIVE);
1040 api::plan_cancel_review_request($plan);
1041 $this->fail('The plan review cannot be cancelled at this stage.');
1042 } catch (coding_exception $e) {
1043 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1046 // Can not cancel review request when not waiting for review.
1047 $this->setUser($user);
1048 $plan->set_status(plan::STATUS_COMPLETE);
1050 api::plan_cancel_review_request($plan);
1051 $this->fail('The plan review cannot be cancelled at this stage.');
1052 } catch (coding_exception $e) {
1053 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
1056 // Cancelling as a reviewer.
1057 $this->setUser($reviewer);
1058 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1060 api::plan_cancel_review_request($plan);
1061 $this->fail('The user can not cancel a review request.');
1062 } catch (required_capability_exception $e) {
1063 $this->assertEquals('nopermissions', $e->errorcode);
1066 // Cancelling review request.
1067 $this->setUser($user);
1068 api::plan_cancel_review_request($plan);
1070 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1072 // Cancelling review request by ID.
1073 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1075 api::plan_cancel_review_request($plan->get_id());
1077 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1081 * Testing starting the review.
1083 public function test_plan_start_review() {
1084 $data = $this->setup_workflow_data();
1086 $lpg = $data['lpg'];
1087 $user = $data['user'];
1088 $reviewer = $data['reviewer'];
1089 $otheruser = $data['otheruser'];
1090 $plan = $data['plan'];
1091 $tplplan = $data['tplplan'];
1093 // Set waiting for review.
1094 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1096 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1099 // Foreign user cannot do anything.
1100 $this->setUser($otheruser);
1102 api::plan_start_review($plan);
1103 $this->fail('The user can not read the plan.');
1104 } catch (required_capability_exception $e) {
1105 $this->assertEquals('nopermissions', $e->errorcode);
1108 // Can not change a plan based on a template.
1109 $this->setUser($reviewer);
1111 api::plan_start_review($tplplan);
1112 $this->fail('The plan is based on a template.');
1113 } catch (coding_exception $e) {
1114 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1117 // Can not start a review when not waiting for review.
1118 $this->setUser($reviewer);
1119 $plan->set_status(plan::STATUS_DRAFT);
1121 api::plan_start_review($plan);
1122 $this->fail('The plan review cannot be started at this stage.');
1123 } catch (coding_exception $e) {
1124 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1127 // Can not start a review when not waiting for review.
1128 $this->setUser($reviewer);
1129 $plan->set_status(plan::STATUS_IN_REVIEW);
1131 api::plan_start_review($plan);
1132 $this->fail('The plan review cannot be started at this stage.');
1133 } catch (coding_exception $e) {
1134 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1137 // Can not start a review when not waiting for review.
1138 $this->setUser($reviewer);
1139 $plan->set_status(plan::STATUS_ACTIVE);
1141 api::plan_start_review($plan);
1142 $this->fail('The plan review cannot be started at this stage.');
1143 } catch (coding_exception $e) {
1144 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1147 // Can not start a review when not waiting for review.
1148 $this->setUser($reviewer);
1149 $plan->set_status(plan::STATUS_COMPLETE);
1151 api::plan_start_review($plan);
1152 $this->fail('The plan review cannot be started at this stage.');
1153 } catch (coding_exception $e) {
1154 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1157 // Starting as the owner.
1158 $this->setUser($user);
1159 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1161 api::plan_start_review($plan);
1162 $this->fail('The user can not start a review.');
1163 } catch (required_capability_exception $e) {
1164 $this->assertEquals('nopermissions', $e->errorcode);
1168 $this->setUser($reviewer);
1169 api::plan_start_review($plan);
1171 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1172 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1174 // Starting review by ID.
1175 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1176 $plan->set_reviewerid(null);
1178 api::plan_start_review($plan->get_id());
1180 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1181 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1185 * Testing stopping the review.
1187 public function test_plan_stop_review() {
1188 $data = $this->setup_workflow_data();
1190 $lpg = $data['lpg'];
1191 $user = $data['user'];
1192 $reviewer = $data['reviewer'];
1193 $otheruser = $data['otheruser'];
1194 $plan = $data['plan'];
1195 $tplplan = $data['tplplan'];
1197 // Set waiting for review.
1198 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1200 $plan->set_status(plan::STATUS_IN_REVIEW);
1203 // Foreign user cannot do anything.
1204 $this->setUser($otheruser);
1206 api::plan_stop_review($plan);
1207 $this->fail('The user can not read the plan.');
1208 } catch (required_capability_exception $e) {
1209 $this->assertEquals('nopermissions', $e->errorcode);
1212 // Can not change a plan based on a template.
1213 $this->setUser($reviewer);
1215 api::plan_stop_review($tplplan);
1216 $this->fail('The plan is based on a template.');
1217 } catch (coding_exception $e) {
1218 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1221 // Can not stop a review whe not in review.
1222 $this->setUser($reviewer);
1223 $plan->set_status(plan::STATUS_DRAFT);
1225 api::plan_stop_review($plan);
1226 $this->fail('The plan review cannot be stopped at this stage.');
1227 } catch (coding_exception $e) {
1228 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1231 // Can not stop a review whe not in review.
1232 $this->setUser($reviewer);
1233 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1235 api::plan_stop_review($plan);
1236 $this->fail('The plan review cannot be stopped at this stage.');
1237 } catch (coding_exception $e) {
1238 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1241 // Can not stop a review whe not in review.
1242 $this->setUser($reviewer);
1243 $plan->set_status(plan::STATUS_ACTIVE);
1245 api::plan_stop_review($plan);
1246 $this->fail('The plan review cannot be stopped at this stage.');
1247 } catch (coding_exception $e) {
1248 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1251 // Can not stop a review whe not in review.
1252 $this->setUser($reviewer);
1253 $plan->set_status(plan::STATUS_COMPLETE);
1255 api::plan_stop_review($plan);
1256 $this->fail('The plan review cannot be stopped at this stage.');
1257 } catch (coding_exception $e) {
1258 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1261 // Stopping as the owner.
1262 $this->setUser($user);
1263 $plan->set_status(plan::STATUS_IN_REVIEW);
1265 api::plan_stop_review($plan);
1266 $this->fail('The user can not stop a review.');
1267 } catch (required_capability_exception $e) {
1268 $this->assertEquals('nopermissions', $e->errorcode);
1272 $this->setUser($reviewer);
1273 api::plan_stop_review($plan);
1275 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1277 // Stopping review by ID.
1278 $plan->set_status(plan::STATUS_IN_REVIEW);
1280 api::plan_stop_review($plan->get_id());
1282 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1286 * Testing approving the plan.
1288 public function test_approve_plan() {
1289 $data = $this->setup_workflow_data();
1291 $lpg = $data['lpg'];
1292 $user = $data['user'];
1293 $reviewer = $data['reviewer'];
1294 $otheruser = $data['otheruser'];
1295 $plan = $data['plan'];
1296 $tplplan = $data['tplplan'];
1298 // Set waiting for review.
1299 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1301 $plan->set_status(plan::STATUS_IN_REVIEW);
1304 // Foreign user cannot do anything.
1305 $this->setUser($otheruser);
1307 api::approve_plan($plan);
1308 $this->fail('The user can not read the plan.');
1309 } catch (required_capability_exception $e) {
1310 $this->assertEquals('nopermissions', $e->errorcode);
1313 // Can not change a plan based on a template.
1314 $this->setUser($reviewer);
1316 api::approve_plan($tplplan);
1317 $this->fail('The plan is based on a template.');
1318 } catch (coding_exception $e) {
1319 $this->assertRegExp('/Template plans are already approved./', $e->getMessage());
1322 // Can not approve a plan already approved.
1323 $this->setUser($reviewer);
1324 $plan->set_status(plan::STATUS_ACTIVE);
1326 api::approve_plan($plan);
1327 $this->fail('The plan cannot be approved at this stage.');
1328 } catch (coding_exception $e) {
1329 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1332 // Can not approve a plan already approved.
1333 $this->setUser($reviewer);
1334 $plan->set_status(plan::STATUS_COMPLETE);
1336 api::approve_plan($plan);
1337 $this->fail('The plan cannot be approved at this stage.');
1338 } catch (coding_exception $e) {
1339 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1342 // Approve as the owner.
1343 $this->setUser($user);
1344 $plan->set_status(plan::STATUS_IN_REVIEW);
1346 api::approve_plan($plan);
1347 $this->fail('The user can not approve the plan.');
1348 } catch (required_capability_exception $e) {
1349 $this->assertEquals('nopermissions', $e->errorcode);
1352 // Approve plan from in review.
1353 $this->setUser($reviewer);
1354 api::approve_plan($plan);
1356 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1358 // Approve plan by ID.
1359 $plan->set_status(plan::STATUS_IN_REVIEW);
1361 api::approve_plan($plan->get_id());
1363 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1365 // Approve plan from draft.
1366 $plan->set_status(plan::STATUS_DRAFT);
1368 api::approve_plan($plan);
1370 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1372 // Approve plan from waiting for review.
1373 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1375 api::approve_plan($plan);
1377 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1381 * Testing stopping the review.
1383 public function test_unapprove_plan() {
1384 $data = $this->setup_workflow_data();
1386 $lpg = $data['lpg'];
1387 $user = $data['user'];
1388 $reviewer = $data['reviewer'];
1389 $otheruser = $data['otheruser'];
1390 $plan = $data['plan'];
1391 $tplplan = $data['tplplan'];
1393 // Set waiting for review.
1394 $tplplan->set_status(plan::STATUS_ACTIVE);
1396 $plan->set_status(plan::STATUS_ACTIVE);
1399 // Foreign user cannot do anything.
1400 $this->setUser($otheruser);
1402 api::unapprove_plan($plan);
1403 $this->fail('The user can not read the plan.');
1404 } catch (required_capability_exception $e) {
1405 $this->assertEquals('nopermissions', $e->errorcode);
1408 // Can not change a plan based on a template.
1409 $this->setUser($reviewer);
1411 api::unapprove_plan($tplplan);
1412 $this->fail('The plan is based on a template.');
1413 } catch (coding_exception $e) {
1414 $this->assertRegExp('/Template plans are always approved./', $e->getMessage());
1417 // Can not unapprove a non-draft plan.
1418 $this->setUser($reviewer);
1419 $plan->set_status(plan::STATUS_DRAFT);
1421 api::unapprove_plan($plan);
1422 $this->fail('The plan cannot be sent back to draft at this stage.');
1423 } catch (coding_exception $e) {
1424 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1427 // Can not unapprove a non-draft plan.
1428 $this->setUser($reviewer);
1429 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1431 api::unapprove_plan($plan);
1432 $this->fail('The plan cannot be sent back to draft at this stage.');
1433 } catch (coding_exception $e) {
1434 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1437 // Can not unapprove a non-draft plan.
1438 $this->setUser($reviewer);
1439 $plan->set_status(plan::STATUS_IN_REVIEW);
1441 api::unapprove_plan($plan);
1442 $this->fail('The plan cannot be sent back to draft at this stage.');
1443 } catch (coding_exception $e) {
1444 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1447 // Can not unapprove a non-draft plan.
1448 $this->setUser($reviewer);
1449 $plan->set_status(plan::STATUS_COMPLETE);
1451 api::unapprove_plan($plan);
1452 $this->fail('The plan cannot be sent back to draft at this stage.');
1453 } catch (coding_exception $e) {
1454 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1457 // Unapprove as the owner.
1458 $this->setUser($user);
1459 $plan->set_status(plan::STATUS_ACTIVE);
1461 api::unapprove_plan($plan);
1462 $this->fail('The user can not unapprove the plan.');
1463 } catch (required_capability_exception $e) {
1464 $this->assertEquals('nopermissions', $e->errorcode);
1468 $this->setUser($reviewer);
1469 api::unapprove_plan($plan);
1471 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1473 // Unapprove plan by ID.
1474 $plan->set_status(plan::STATUS_ACTIVE);
1476 api::unapprove_plan($plan->get_id());
1478 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1482 * Test update plan and the managing of archived user competencies.
1484 public function test_update_plan_manage_archived_competencies() {
1487 $this->resetAfterTest(true);
1488 $dg = $this->getDataGenerator();
1489 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1491 $syscontext = context_system::instance();
1493 // Create users and roles for the test.
1494 $user = $dg->create_user();
1495 $manageownrole = $dg->create_role(array(
1496 'name' => 'User manage own',
1497 'shortname' => 'manageown'
1499 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1500 assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1501 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
1502 assign_capability('moodle/competency:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
1503 $dg->role_assign($manageownrole, $user->id, $syscontext->id);
1504 $this->setUser($user);
1506 // Create a framework and assign competencies.
1507 $framework = $lpg->create_framework();
1508 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1509 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1510 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1512 // Create two plans and assign competencies.
1513 $plan = $lpg->create_plan(array('userid' => $user->id));
1514 $otherplan = $lpg->create_plan(array('userid' => $user->id));
1516 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c1->get_id()));
1517 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c2->get_id()));
1518 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c3->get_id()));
1519 $lpg->create_plan_competency(array('planid' => $otherplan->get_id(), 'competencyid' => $c1->get_id()));
1522 $lpg->create_user_competency(array(
1523 'userid' => $user->id,
1524 'competencyid' => $c1->get_id(),
1525 'proficiency' => true,
1528 $lpg->create_user_competency(array(
1529 'userid' => $user->id,
1530 'competencyid' => $c2->get_id(),
1531 'proficiency' => false,
1536 // Change status of the plan to complete.
1537 $record = $plan->to_record();
1538 $record->status = \core_competency\plan::STATUS_COMPLETE;
1541 $plan = api::update_plan($record);
1542 $this->fail('We cannot complete a plan using api::update_plan().');
1543 } catch (coding_exception $e) {
1546 api::complete_plan($plan);
1548 // Check that user compretencies are now in user_competency_plan objects and still in user_competency.
1549 $this->assertEquals(2, \core_competency\user_competency::count_records());
1550 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
1552 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
1554 $this->assertEquals($uclist[0]->get_userid(), $usercompetenciesplan[0]->get_userid());
1555 $this->assertEquals($uclist[0]->get_competencyid(), $usercompetenciesplan[0]->get_competencyid());
1556 $this->assertEquals($uclist[0]->get_proficiency(), (bool) $usercompetenciesplan[0]->get_proficiency());
1557 $this->assertEquals($uclist[0]->get_grade(), $usercompetenciesplan[0]->get_grade());
1558 $this->assertEquals($plan->get_id(), $usercompetenciesplan[0]->get_planid());
1560 $this->assertEquals($uclist[1]->get_userid(), $usercompetenciesplan[1]->get_userid());
1561 $this->assertEquals($uclist[1]->get_competencyid(), $usercompetenciesplan[1]->get_competencyid());
1562 $this->assertEquals($uclist[1]->get_proficiency(), (bool) $usercompetenciesplan[1]->get_proficiency());
1563 $this->assertEquals($uclist[1]->get_grade(), $usercompetenciesplan[1]->get_grade());
1564 $this->assertEquals($plan->get_id(), $usercompetenciesplan[1]->get_planid());
1566 $this->assertEquals($user->id, $usercompetenciesplan[2]->get_userid());
1567 $this->assertEquals($c3->get_id(), $usercompetenciesplan[2]->get_competencyid());
1568 $this->assertNull($usercompetenciesplan[2]->get_proficiency());
1569 $this->assertNull($usercompetenciesplan[2]->get_grade());
1570 $this->assertEquals($plan->get_id(), $usercompetenciesplan[2]->get_planid());
1572 // Change status of the plan to active.
1573 $record = $plan->to_record();
1574 $record->status = \core_competency\plan::STATUS_ACTIVE;
1577 api::update_plan($record);
1578 $this->fail('Completed plan can not be edited');
1579 } catch (coding_exception $e) {
1583 api::reopen_plan($record->id);
1584 // Check that user_competency_plan objects are deleted if the plan status is changed to another status.
1585 $this->assertEquals(2, \core_competency\user_competency::count_records());
1586 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
1590 * Test completing plan does not change the order of competencies.
1592 public function test_complete_plan_doesnot_change_order() {
1595 $this->resetAfterTest(true);
1596 $this->setAdminUser();
1597 $dg = $this->getDataGenerator();
1598 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1600 $syscontext = context_system::instance();
1602 // Create users and roles for the test.
1603 $user = $dg->create_user();
1605 // Create a framework and assign competencies.
1606 $framework = $lpg->create_framework();
1607 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1608 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1609 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1611 // Create two plans and assign competencies.
1612 $plan = $lpg->create_plan(array('userid' => $user->id));
1614 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c1->get_id()));
1615 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c2->get_id()));
1616 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c3->get_id()));
1618 // Changing competencies order in plan competency.
1619 api::reorder_plan_competency($plan->get_id(), $c1->get_id(), $c3->get_id());
1621 $competencies = api::list_plan_competencies($plan);
1622 $this->assertEquals($c2->get_id(), $competencies[0]->competency->get_id());
1623 $this->assertEquals($c3->get_id(), $competencies[1]->competency->get_id());
1624 $this->assertEquals($c1->get_id(), $competencies[2]->competency->get_id());
1627 api::complete_plan($plan);
1629 $competencies = api::list_plan_competencies($plan);
1631 // Completing plan does not change order.
1632 $this->assertEquals($c2->get_id(), $competencies[0]->competency->get_id());
1633 $this->assertEquals($c3->get_id(), $competencies[1]->competency->get_id());
1634 $this->assertEquals($c1->get_id(), $competencies[2]->competency->get_id());
1636 // Testing plan based on template.
1637 $template = $lpg->create_template();
1638 $framework = $lpg->create_framework();
1639 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1640 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1641 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1643 $lpg->create_template_competency(array(
1644 'templateid' => $template->get_id(),
1645 'competencyid' => $c1->get_id()
1647 $lpg->create_template_competency(array(
1648 'templateid' => $template->get_id(),
1649 'competencyid' => $c2->get_id()
1651 $lpg->create_template_competency(array(
1652 'templateid' => $template->get_id(),
1653 'competencyid' => $c3->get_id()
1655 // Reorder competencies in template.
1656 api::reorder_template_competency($template->get_id(), $c1->get_id(), $c3->get_id());
1658 // Create plan from template.
1659 $plan = api::create_plan_from_template($template->get_id(), $user->id);
1661 $competencies = api::list_plan_competencies($plan);
1663 // Completing plan does not change order.
1664 $this->assertEquals($c2->get_id(), $competencies[0]->competency->get_id());
1665 $this->assertEquals($c3->get_id(), $competencies[1]->competency->get_id());
1666 $this->assertEquals($c1->get_id(), $competencies[2]->competency->get_id());
1669 api::complete_plan($plan);
1671 $competencies = api::list_plan_competencies($plan);
1673 // Completing plan does not change order.
1674 $this->assertEquals($c2->get_id(), $competencies[0]->competency->get_id());
1675 $this->assertEquals($c3->get_id(), $competencies[1]->competency->get_id());
1676 $this->assertEquals($c1->get_id(), $competencies[2]->competency->get_id());
1680 * Test remove plan and the managing of archived user competencies.
1682 public function test_delete_plan_manage_archived_competencies() {
1683 $this->resetAfterTest(true);
1684 $dg = $this->getDataGenerator();
1685 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1687 $syscontext = context_system::instance();
1689 // Create user and role for the test.
1690 $user = $dg->create_user();
1691 $managerole = $dg->create_role(array(
1692 'name' => 'User manage own',
1693 'shortname' => 'manageown'
1695 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $managerole, $syscontext->id);
1696 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $managerole, $syscontext->id);
1697 $dg->role_assign($managerole, $user->id, $syscontext->id);
1698 $this->setUser($user);
1700 // Create a framework and assign competencies.
1701 $framework = $lpg->create_framework();
1702 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1703 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1704 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1706 // Create completed plan with records in user_competency.
1707 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
1709 $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c1->get_id()));
1710 $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c2->get_id()));
1712 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
1713 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id()));
1715 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
1716 'planid' => $completedplan->get_id()));
1717 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
1718 'planid' => $completedplan->get_id()));
1720 api::delete_plan($completedplan->get_id());
1722 // Check that achived user competencies are deleted.
1723 $this->assertEquals(0, \core_competency\plan::count_records());
1724 $this->assertEquals(2, \core_competency\user_competency::count_records());
1725 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
1729 * Test listing of plan competencies.
1731 public function test_list_plan_competencies_manage_archived_competencies() {
1732 $this->resetAfterTest(true);
1733 $dg = $this->getDataGenerator();
1734 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1736 $syscontext = context_system::instance();
1738 // Create user and role for the test.
1739 $user = $dg->create_user();
1740 $viewrole = $dg->create_role(array(
1741 'name' => 'User view',
1742 'shortname' => 'view'
1744 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $viewrole, $syscontext->id);
1745 assign_capability('moodle/competency:planview', CAP_ALLOW, $viewrole, $syscontext->id);
1746 $dg->role_assign($viewrole, $user->id, $syscontext->id);
1747 $this->setUser($user);
1749 // Create a framework and assign competencies.
1750 $framework = $lpg->create_framework();
1751 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1752 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1753 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1755 // Create draft plan with records in user_competency.
1756 $draftplan = $lpg->create_plan(array('userid' => $user->id));
1758 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c1->get_id()));
1759 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c2->get_id()));
1760 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c3->get_id()));
1762 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
1763 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id()));
1765 // Check that user_competency objects are returned when plan status is not complete.
1766 $plancompetencies = api::list_plan_competencies($draftplan);
1768 $this->assertCount(3, $plancompetencies);
1769 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[0]->usercompetency);
1770 $this->assertEquals($uc1->get_id(), $plancompetencies[0]->usercompetency->get_id());
1771 $this->assertNull($plancompetencies[0]->usercompetencyplan);
1773 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[1]->usercompetency);
1774 $this->assertEquals($uc2->get_id(), $plancompetencies[1]->usercompetency->get_id());
1775 $this->assertNull($plancompetencies[1]->usercompetencyplan);
1777 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[2]->usercompetency);
1778 $this->assertEquals(0, $plancompetencies[2]->usercompetency->get_id());
1779 $this->assertNull($plancompetencies[2]->usercompetencyplan);
1781 // Create completed plan with records in user_competency_plan.
1782 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
1784 $pc1 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c1->get_id()));
1785 $pc2 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c2->get_id()));
1786 $pc3 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c3->get_id()));
1788 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
1789 'planid' => $completedplan->get_id()));
1790 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
1791 'planid' => $completedplan->get_id()));
1792 $ucp3 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c3->get_id(),
1793 'planid' => $completedplan->get_id()));
1795 // Check that user_competency_plan objects are returned when plan status is complete.
1796 $plancompetencies = api::list_plan_competencies($completedplan);
1798 $this->assertCount(3, $plancompetencies);
1799 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[0]->usercompetencyplan);
1800 $this->assertEquals($ucp1->get_id(), $plancompetencies[0]->usercompetencyplan->get_id());
1801 $this->assertNull($plancompetencies[0]->usercompetency);
1802 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[1]->usercompetencyplan);
1803 $this->assertEquals($ucp2->get_id(), $plancompetencies[1]->usercompetencyplan->get_id());
1804 $this->assertNull($plancompetencies[1]->usercompetency);
1805 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[2]->usercompetencyplan);
1806 $this->assertEquals($ucp3->get_id(), $plancompetencies[2]->usercompetencyplan->get_id());
1807 $this->assertNull($plancompetencies[2]->usercompetency);
1810 public function test_create_template_cohort() {
1811 $this->resetAfterTest(true);
1812 $this->setAdminUser();
1814 $dg = $this->getDataGenerator();
1815 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1817 $c1 = $dg->create_cohort();
1818 $c2 = $dg->create_cohort();
1819 $t1 = $lpg->create_template();
1820 $t2 = $lpg->create_template();
1822 $this->assertEquals(0, \core_competency\template_cohort::count_records());
1824 // Create two relations with mixed parameters.
1825 $result = api::create_template_cohort($t1->get_id(), $c1->id);
1826 $result = api::create_template_cohort($t1, $c2);
1828 $this->assertEquals(2, \core_competency\template_cohort::count_records());
1829 $this->assertInstanceOf('core_competency\template_cohort', $result);
1830 $this->assertEquals($c2->id, $result->get_cohortid());
1831 $this->assertEquals($t1->get_id(), $result->get_templateid());
1832 $this->assertEquals(2, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1833 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1836 public function test_create_template_cohort_permissions() {
1837 $this->resetAfterTest(true);
1839 $dg = $this->getDataGenerator();
1840 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1841 $cat = $dg->create_category();
1842 $catcontext = context_coursecat::instance($cat->id);
1843 $syscontext = context_system::instance();
1845 $user = $dg->create_user();
1846 $role = $dg->create_role();
1847 assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $syscontext->id, true);
1848 $dg->role_assign($role, $user->id, $syscontext->id);
1850 $cohortrole = $dg->create_role();
1851 assign_capability('moodle/cohort:view', CAP_ALLOW, $cohortrole, $syscontext->id, true);
1853 accesslib_clear_all_caches_for_unit_testing();
1855 $c1 = $dg->create_cohort();
1856 $c2 = $dg->create_cohort(array('visible' => 0, 'contextid' => $catcontext->id));
1857 $t1 = $lpg->create_template();
1859 $this->assertEquals(0, \core_competency\template_cohort::count_records());
1861 $this->setUser($user);
1862 $result = api::create_template_cohort($t1, $c1);
1863 $this->assertInstanceOf('core_competency\\template_cohort', $result);
1866 $result = api::create_template_cohort($t1, $c2);
1867 $this->fail('Permission required.');
1868 } catch(required_capability_exception $e) {
1869 // That's what should happen.
1872 // Try again with the right permissions.
1873 $dg->role_assign($cohortrole, $user->id, $catcontext->id);
1874 accesslib_clear_all_caches_for_unit_testing();
1876 $result = api::create_template_cohort($t1, $c2);
1877 $this->assertInstanceOf('core_competency\\template_cohort', $result);
1880 public function test_delete_template() {
1881 $this->resetAfterTest(true);
1882 $this->setAdminUser();
1884 $dg = $this->getDataGenerator();
1885 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1887 $c1 = $dg->create_cohort();
1888 $c2 = $dg->create_cohort();
1889 $template = $lpg->create_template();
1890 $id = $template->get_id();
1892 // Create 2 template cohorts.
1893 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get_id(), 'cohortid' => $c1->id));
1894 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get_id(), 'cohortid' => $c2->id));
1897 $this->assertTrue(\core_competency\template::record_exists($id));
1898 $this->assertEquals(2, \core_competency\template_cohort::count_records(array('templateid' => $id)));
1900 $result = api::delete_template($template->get_id());
1901 $this->assertTrue($result);
1903 // Check that the template deos not exist anymore.
1904 $this->assertFalse(\core_competency\template::record_exists($id));
1906 // Test if associated cohorts are also deleted.
1907 $this->assertEquals(0, \core_competency\template_cohort::count_records(array('templateid' => $id)));
1910 public function test_delete_template_cohort() {
1911 $this->resetAfterTest(true);
1912 $this->setAdminUser();
1914 $dg = $this->getDataGenerator();
1915 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1917 $c1 = $dg->create_cohort();
1918 $c2 = $dg->create_cohort();
1919 $t1 = $lpg->create_template();
1920 $t2 = $lpg->create_template();
1921 $tc1 = $lpg->create_template_cohort(array('templateid' => $t1->get_id(), 'cohortid' => $c1->id));
1922 $tc1 = $lpg->create_template_cohort(array('templateid' => $t2->get_id(), 'cohortid' => $c2->id));
1924 $this->assertEquals(2, \core_competency\template_cohort::count_records());
1925 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1926 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1929 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1930 $this->assertTrue($result);
1931 $this->assertEquals(1, \core_competency\template_cohort::count_records());
1932 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1933 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1935 // Delete non-existant.
1936 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1937 $this->assertTrue($result);
1938 $this->assertEquals(1, \core_competency\template_cohort::count_records());
1939 $this->assertEquals(0, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1940 $this->assertEquals(1, \core_competency\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1943 public function test_add_evidence_log() {
1944 $this->resetAfterTest(true);
1945 $dg = $this->getDataGenerator();
1946 $lpg = $dg->get_plugin_generator('core_competency');
1948 $u1 = $dg->create_user();
1949 $u1ctx = context_user::instance($u1->id);
1950 $f1 = $lpg->create_framework();
1951 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1952 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1954 // Creating a standard evidence with minimal information.
1955 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata', 'error');
1957 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1958 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
1959 $this->assertSame(null, $uc->get_grade());
1960 $this->assertSame(null, $uc->get_proficiency());
1961 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1962 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1963 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get_action());
1964 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1965 $this->assertEquals('error', $evidence->get_desccomponent());
1966 $this->assertSame(null, $evidence->get_desca());
1967 $this->assertSame(null, $evidence->get_url());
1968 $this->assertSame(null, $evidence->get_grade());
1969 $this->assertSame(null, $evidence->get_actionuserid());
1971 // Creating a standard evidence with more information.
1972 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata', 'error',
1973 '$a', false, 'http://moodle.org', null, 2, 'The evidence of prior learning were reviewed.');
1975 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1976 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
1977 $this->assertSame(null, $uc->get_grade());
1978 $this->assertSame(null, $uc->get_proficiency());
1979 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1980 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1981 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get_action());
1982 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1983 $this->assertEquals('error', $evidence->get_desccomponent());
1984 $this->assertEquals('$a', $evidence->get_desca());
1985 $this->assertEquals('http://moodle.org', $evidence->get_url());
1986 $this->assertSame(null, $evidence->get_grade());
1987 $this->assertEquals(2, $evidence->get_actionuserid());
1988 $this->assertSame('The evidence of prior learning were reviewed.', $evidence->get_note());
1990 // Creating a standard evidence and send for review.
1991 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
1992 'error', null, true);
1994 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
1995 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
1997 // Trying to pass a grade should fail.
1999 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2000 'error', null, false, null, 1);
2001 $this->fail('A grade can not be set');
2002 } catch (coding_exception $e) {
2003 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2007 public function test_add_evidence_complete() {
2008 $this->resetAfterTest(true);
2009 $dg = $this->getDataGenerator();
2010 $lpg = $dg->get_plugin_generator('core_competency');
2012 $u1 = $dg->create_user();
2013 $u1ctx = context_user::instance($u1->id);
2014 $scale = $dg->create_scale(array('scale' => 'A,B,C,D'));
2015 $scaleconfig = array(array('scaleid' => $scale->id));
2016 $scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 1, 'proficient' => 0);
2017 $scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 1);
2018 $scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 0, 'proficient' => 1);
2019 $c2scaleconfig = array(array('scaleid' => $scale->id));
2020 $c2scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 0, 'proficient' => 1);
2021 $c2scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 0);
2022 $c2scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 1, 'proficient' => 1);
2023 $f1 = $lpg->create_framework(array('scaleid' => $scale->id, 'scaleconfiguration' => $scaleconfig));
2024 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2025 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'scaleid' => $scale->id,
2026 'scaleconfiguration' => $c2scaleconfig));
2027 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2029 // Creating an evidence with minimal information.
2030 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2033 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2034 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2035 $this->assertEquals(2, $uc->get_grade()); // The grade has been set automatically to the framework default.
2036 $this->assertEquals(0, $uc->get_proficiency());
2037 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2038 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2039 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
2040 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2041 $this->assertEquals('error', $evidence->get_desccomponent());
2042 $this->assertSame(null, $evidence->get_desca());
2043 $this->assertSame(null, $evidence->get_url());
2044 $this->assertEquals(2, $evidence->get_grade());
2045 $this->assertSame(null, $evidence->get_actionuserid());
2047 // Creating an evidence complete on competency with custom scale.
2048 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2051 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2052 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2053 $this->assertEquals(4, $uc->get_grade()); // The grade has been set automatically to the competency default.
2054 $this->assertEquals(true, $uc->get_proficiency());
2055 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2056 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2057 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
2058 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2059 $this->assertEquals('error', $evidence->get_desccomponent());
2060 $this->assertSame(null, $evidence->get_desca());
2061 $this->assertSame(null, $evidence->get_url());
2062 $this->assertEquals(4, $evidence->get_grade());
2063 $this->assertSame(null, $evidence->get_actionuserid());
2065 // Creating an evidence complete on a user competency with an existing grade.
2066 $uc = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c3->get_id(), 'grade' => 1,
2067 'proficiency' => 0));
2068 $this->assertEquals(1, $uc->get_grade());
2069 $this->assertEquals(0, $uc->get_proficiency());
2070 $evidence = api::add_evidence($u1->id, $c3->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2074 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2075 $this->assertEquals(1, $uc->get_grade()); // The grade has not been changed.
2076 $this->assertEquals(0, $uc->get_proficiency());
2077 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2078 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2079 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
2080 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2081 $this->assertEquals('error', $evidence->get_desccomponent());
2082 $this->assertSame(null, $evidence->get_desca());
2083 $this->assertSame(null, $evidence->get_url());
2084 $this->assertEquals(2, $evidence->get_grade()); // The complete grade has been set.
2085 $this->assertSame(null, $evidence->get_actionuserid());
2087 // Creating a standard evidence and send for review.
2088 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2089 'error', null, true);
2091 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2092 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2094 // Trying to pass a grade should throw an exception.
2096 api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
2097 'error', null, false, null, 1);
2098 } catch (coding_exception $e) {
2099 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2103 public function test_add_evidence_override() {
2104 $this->resetAfterTest(true);
2105 $dg = $this->getDataGenerator();
2106 $lpg = $dg->get_plugin_generator('core_competency');
2108 $u1 = $dg->create_user();
2109 $u1ctx = context_user::instance($u1->id);
2110 $f1 = $lpg->create_framework();
2111 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2113 // Creating an evidence with minimal information.
2114 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2117 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2118 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2119 $this->assertSame(null, $uc->get_grade()); // We overrode with 'null'.
2120 $this->assertSame(null, $uc->get_proficiency());
2121 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2122 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2123 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
2124 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2125 $this->assertEquals('error', $evidence->get_desccomponent());
2126 $this->assertSame(null, $evidence->get_desca());
2127 $this->assertSame(null, $evidence->get_url());
2128 $this->assertSame(null, $evidence->get_grade()); // We overrode with 'null'.
2129 $this->assertSame(null, $evidence->get_actionuserid());
2131 // Creating an evidence with a grade information.
2132 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2133 'error', null, false, null, 3);
2135 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2136 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2137 $this->assertEquals(3, $uc->get_grade());
2138 $this->assertEquals(true, $uc->get_proficiency());
2139 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2140 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2141 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
2142 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2143 $this->assertEquals('error', $evidence->get_desccomponent());
2144 $this->assertSame(null, $evidence->get_desca());
2145 $this->assertSame(null, $evidence->get_url());
2146 $this->assertEquals(3, $evidence->get_grade());
2147 $this->assertSame(null, $evidence->get_actionuserid());
2149 // Creating an evidence with another grade information.
2150 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2151 'error', null, false, null, 1);
2153 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2154 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
2155 $this->assertEquals(1, $uc->get_grade());
2156 $this->assertEquals(0, $uc->get_proficiency());
2157 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2158 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
2159 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
2160 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
2161 $this->assertEquals('error', $evidence->get_desccomponent());
2162 $this->assertSame(null, $evidence->get_desca());
2163 $this->assertSame(null, $evidence->get_url());
2164 $this->assertEquals(1, $evidence->get_grade());
2165 $this->assertSame(null, $evidence->get_actionuserid());
2167 // Creating reverting the grade and send for review.
2168 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
2169 'error', null, true);
2171 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2172 $this->assertSame(null, $uc->get_grade());
2173 $this->assertSame(null, $uc->get_proficiency());
2174 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2175 $this->assertSame(null, $evidence->get_grade());
2178 public function test_add_evidence_and_send_for_review() {
2179 $this->resetAfterTest(true);
2180 $dg = $this->getDataGenerator();
2181 $lpg = $dg->get_plugin_generator('core_competency');
2183 $u1 = $dg->create_user();
2184 $u1ctx = context_user::instance($u1->id);
2185 $f1 = $lpg->create_framework();
2186 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2188 // Non-existing user competencies are created up for review.
2189 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2190 'error', null, true);
2191 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2192 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2194 // Existing user competencies sent for review don't change.
2195 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2196 'error', null, true);
2198 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2200 // A user competency with a status non-idle won't change.
2201 $uc->set_status(\core_competency\user_competency::STATUS_IN_REVIEW);
2203 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
2204 'error', null, true);
2206 $this->assertEquals(\core_competency\user_competency::STATUS_IN_REVIEW, $uc->get_status());
2210 * Test add evidence for existing user_competency.
2212 public function test_add_evidence_existing_user_competency() {
2213 $this->resetAfterTest(true);
2214 $dg = $this->getDataGenerator();
2215 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2217 $syscontext = context_system::instance();
2220 $user = $dg->create_user();
2221 $this->setUser($user);
2223 // Create a framework and assign competencies.
2224 $framework = $lpg->create_framework();
2225 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2226 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2227 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2228 $uc = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
2229 $this->assertSame(null, $uc->get_grade());
2230 $this->assertSame(null, $uc->get_proficiency());
2232 // Create an evidence and check it was created with the right usercomptencyid and information.
2233 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
2234 'invalidevidencedesc', 'tool_lp', array('a' => 'b'), false, 'http://moodle.org', 1, 2);
2235 $this->assertEquals(1, \core_competency\evidence::count_records());
2239 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2240 $this->assertEquals('invalidevidencedesc', $evidence->get_descidentifier());
2241 $this->assertEquals('tool_lp', $evidence->get_desccomponent());
2242 $this->assertEquals((object) array('a' => 'b'), $evidence->get_desca());
2243 $this->assertEquals('http://moodle.org', $evidence->get_url());
2244 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
2245 $this->assertEquals(2, $evidence->get_actionuserid());
2246 $this->assertEquals(1, $evidence->get_grade());
2247 $this->assertEquals(1, $uc->get_grade());
2248 $this->assertEquals(0, $uc->get_proficiency());
2252 * Test add evidence for non-existing user_competency.
2254 public function test_add_evidence_no_existing_user_competency() {
2255 $this->resetAfterTest(true);
2256 $dg = $this->getDataGenerator();
2257 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2259 $syscontext = context_system::instance();
2262 $user = $dg->create_user();
2263 $this->setUser($user);
2265 // Create a framework and assign competencies.
2266 $framework = $lpg->create_framework();
2267 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2268 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2269 $this->assertEquals(0, \core_competency\user_competency::count_records());
2271 // Create an evidence without a user competency record.
2272 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
2273 'invalidevidencedesc', 'tool_lp', 'Hello world!', false, 'http://moodle.org', 1, 2);
2274 $this->assertEquals(1, \core_competency\evidence::count_records());
2275 $this->assertEquals(1, \core_competency\user_competency::count_records());
2277 $uc = \core_competency\user_competency::get_record(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
2279 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2280 $this->assertEquals('invalidevidencedesc', $evidence->get_descidentifier());
2281 $this->assertEquals('tool_lp', $evidence->get_desccomponent());
2282 $this->assertEquals('Hello world!', $evidence->get_desca());
2283 $this->assertEquals('http://moodle.org', $evidence->get_url());
2284 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
2285 $this->assertEquals(2, $evidence->get_actionuserid());
2286 $this->assertEquals(1, $evidence->get_grade());
2287 $this->assertEquals(1, $uc->get_grade());
2288 $this->assertEquals(0, $uc->get_proficiency());
2291 public function test_add_evidence_applies_competency_rules() {
2292 $this->resetAfterTest(true);
2293 $dg = $this->getDataGenerator();
2294 $lpg = $dg->get_plugin_generator('core_competency');
2295 $syscontext = context_system::instance();
2296 $ctxid = $syscontext->id;
2298 $u1 = $dg->create_user();
2300 // Setting up the framework.
2301 $f1 = $lpg->create_framework();
2302 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2303 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2304 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2305 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2306 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c2->get_id()));
2307 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2308 $c3a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c3->get_id()));
2309 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2310 $c4a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c4->get_id()));
2311 $c5 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2313 // Setting up the rules.
2314 $c1->set_ruletype('core_competency\\competency_rule_all');
2315 $c1->set_ruleoutcome(\core_competency\competency::OUTCOME_COMPLETE);
2317 $c2->set_ruletype('core_competency\\competency_rule_all');
2318 $c2->set_ruleoutcome(\core_competency\competency::OUTCOME_RECOMMEND);
2320 $c3->set_ruletype('core_competency\\competency_rule_all');
2321 $c3->set_ruleoutcome(\core_competency\competency::OUTCOME_EVIDENCE);
2323 $c4->set_ruletype('core_competency\\competency_rule_all');
2324 $c4->set_ruleoutcome(\core_competency\competency::OUTCOME_NONE);
2327 // Confirm the current data.
2328 $this->assertEquals(0, user_competency::count_records());
2329 $this->assertEquals(0, evidence::count_records());
2332 // First let's confirm that evidence not marking a completion have no impact.
2333 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_LOG, 'commentincontext', 'core');
2334 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get_id()));
2335 $this->assertSame(null, $uc1a->get_proficiency());
2336 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c1->get_id())));
2338 // Now let's try complete a competency but the rule won't match (not all children are complete).
2339 // The parent (the thing with the rule) will be created but won't have any evidence attached, and not
2340 // not be marked as completed.
2341 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2342 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get_id()));
2343 $this->assertEquals(true, $uc1a->get_proficiency());
2344 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2345 $this->assertSame(null, $uc1->get_proficiency());
2346 $this->assertEquals(0, evidence::count_records(array('usercompetencyid' => $uc1->get_id())));
2348 // Now we complete the other child. That will mark the parent as complete with an evidence.
2349 api::add_evidence($u1->id, $c1b, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2350 $uc1b = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1b->get_id()));
2351 $this->assertEquals(true, $uc1a->get_proficiency());
2352 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2353 $this->assertEquals(true, $uc1->get_proficiency());
2354 $this->assertEquals(user_competency::STATUS_IDLE, $uc1->get_status());
2355 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc1->get_id())));
2357 // Check rule recommending.
2358 api::add_evidence($u1->id, $c2a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2359 $uc2a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2a->get_id()));
2360 $this->assertEquals(true, $uc1a->get_proficiency());
2361 $uc2 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2362 $this->assertSame(null, $uc2->get_proficiency());
2363 $this->assertEquals(user_competency::STATUS_WAITING_FOR_REVIEW, $uc2->get_status());
2364 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc2->get_id())));
2366 // Check rule evidence.
2367 api::add_evidence($u1->id, $c3a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2368 $uc3a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3a->get_id()));
2369 $this->assertEquals(true, $uc1a->get_proficiency());
2370 $uc3 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get_id()));
2371 $this->assertSame(null, $uc3->get_proficiency());
2372 $this->assertEquals(user_competency::STATUS_IDLE, $uc3->get_status());
2373 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc3->get_id())));
2375 // Check rule nothing.
2376 api::add_evidence($u1->id, $c4a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2377 $uc4a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4a->get_id()));
2378 $this->assertEquals(true, $uc1a->get_proficiency());
2379 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c4->get_id())));
2381 // Check marking on something that has no parent. This just checks that nothing breaks.
2382 api::add_evidence($u1->id, $c5, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2386 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2387 * grading a user competency in the system context.
2389 public function test_add_evidence_for_user_competency_course_grade_outside_course() {
2390 $this->resetAfterTest(true);
2391 $dg = $this->getDataGenerator();
2392 $syscontext = context_system::instance();
2394 // Create a student.
2395 $student = $dg->create_user();
2397 // Create a competency for the course.
2398 $lpg = $dg->get_plugin_generator('core_competency');
2399 $framework = $lpg->create_framework();
2400 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2403 api::add_evidence($student->id, $comp, $syscontext, evidence::ACTION_OVERRIDE,
2404 'commentincontext', 'core', null, false, null, 1);
2406 // Query for user_competency_course data.
2407 $filterparams = array(
2408 'userid' => $student->id,
2409 'competencyid' => $comp->get_id(),
2411 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
2412 // There should be no user_competency_course object created when grading.
2413 $this->assertFalse($usercompcourse);
2417 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2418 * grading a user competency in a course.
2420 public function test_add_evidence_user_competency_course_grade_in_course() {
2423 $this->resetAfterTest(true);
2424 $dg = $this->getDataGenerator();
2427 $course = $dg->create_course();
2428 $record = array('courseid' => $course->id, 'pushratingstouserplans' => false);
2429 $settings = new course_competency_settings(0, (object) $record);
2430 $settings->create();
2431 $coursecontext = context_course::instance($course->id);
2433 // Create a student and enrol into the course.
2434 $student = $dg->create_user();
2435 $studentarch = get_archetype_roles('student');
2436 $studentrole = array_shift($studentarch);
2437 $dg->role_assign($studentrole->id, $student->id, $coursecontext->id);
2438 $dg->enrol_user($student->id, $course->id, $studentrole->id);
2440 // Create a competency for the course.
2441 $lpg = $dg->get_plugin_generator('core_competency');
2442 $framework = $lpg->create_framework();
2443 // Do not push ratings from course to user plans.
2444 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2445 $lpg->create_course_competency(array('courseid' => $course->id, 'competencyid' => $comp->get_id()));
2447 // Query for user_competency_course data.
2448 $filterparams = array(
2449 'userid' => $student->id,
2450 'competencyid' => $comp->get_id(),
2451 'courseid' => $course->id
2454 // Add evidence that sets a grade to the course.
2455 $evidence = api::add_evidence($student->id, $comp, $coursecontext, evidence::ACTION_OVERRIDE,
2456 'commentincontext', 'core', null, false, null, 3, $USER->id);
2457 // Get user competency course record.
2458 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
2459 // There should be a user_competency_course object when adding a grade.
2460 $this->assertNotEmpty($usercompcourse);
2461 $grade = $evidence->get_grade();
2462 $this->assertEquals($grade, $usercompcourse->get_grade());
2463 $this->assertEquals(3, $usercompcourse->get_grade());
2464 $proficiency = $comp->get_proficiency_of_grade($grade);
2465 $this->assertEquals($proficiency, $usercompcourse->get_proficiency());
2467 // Confirm that the user competency's grade/proficiency has not been affected by the grade.
2468 $usercompetencyparams = [
2469 'userid' => $student->id,
2470 'competencyid' => $comp->get_id(),
2472 $usercompetency = \core_competency\user_competency::get_record($usercompetencyparams);
2473 $this->assertNotEmpty($usercompetency);
2474 $this->assertNotEquals($usercompcourse->get_grade(), $usercompetency->get_grade());
2475 $this->assertNotEquals($usercompcourse->get_proficiency(), $usercompetency->get_proficiency());
2478 public function test_observe_course_completed() {
2479 $this->resetAfterTest(true);
2480 $dg = $this->getDataGenerator();
2481 $lpg = $dg->get_plugin_generator('core_competency');
2483 // Set-up users, framework, competencies and course competencies.
2484 $course = $dg->create_course();
2485 $coursectx = context_course::instance($course->id);
2486 $u1 = $dg->create_user();
2487 $f1 = $lpg->create_framework();
2488 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2489 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2490 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2491 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2492 $cc1 = $lpg->create_course_competency(array('competencyid' => $c1->get_id(), 'courseid' => $course->id,
2493 'ruleoutcome' => \core_competency\course_competency::OUTCOME_NONE));
2494 $cc2 = $lpg->create_course_competency(array('competencyid' => $c2->get_id(), 'courseid' => $course->id,
2495 'ruleoutcome' => \core_competency\course_competency::OUTCOME_EVIDENCE));
2496 $cc3 = $lpg->create_course_competency(array('competencyid' => $c3->get_id(), 'courseid' => $course->id,
2497 'ruleoutcome' => \core_competency\course_competency::OUTCOME_RECOMMEND));
2498 $cc4 = $lpg->create_course_competency(array('competencyid' => $c4->get_id(), 'courseid' => $course->id,
2499 'ruleoutcome' => \core_competency\course_competency::OUTCOME_COMPLETE));
2501 $event = \core\event\course_completed::create(array(
2503 'relateduserid' => $u1->id,
2504 'context' => $coursectx,
2505 'courseid' => $course->id,
2506 'other' => array('relateduserid' => $u1->id)
2508 $this->assertEquals(0, \core_competency\user_competency::count_records());
2509 $this->assertEquals(0, \core_competency\evidence::count_records());
2512 api::observe_course_completed($event);
2513 $this->assertEquals(3, \core_competency\user_competency::count_records());
2514 $this->assertEquals(3, \core_competency\evidence::count_records());
2516 // Outcome NONE did nothing.
2517 $this->assertFalse(\core_competency\user_competency::record_exists_select('userid = :uid AND competencyid = :cid', array(
2518 'uid' => $u1->id, 'cid' => $c1->get_id()
2521 // Outcome evidence.
2522 $uc2 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2523 $ev2 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc2->get_id()));
2525 $this->assertEquals(null, $uc2->get_grade());
2526 $this->assertEquals(null, $uc2->get_proficiency());
2527 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc2->get_status());
2529 $this->assertEquals('evidence_coursecompleted', $ev2->get_descidentifier());
2530 $this->assertEquals('tool_lp', $ev2->get_desccomponent());
2531 $this->assertEquals($course->shortname, $ev2->get_desca());
2532 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev2->get_url());
2533 $this->assertEquals(null, $ev2->get_grade());
2534 $this->assertEquals($coursectx->id, $ev2->get_contextid());
2535 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev2->get_action());
2536 $this->assertEquals(null, $ev2->get_actionuserid());
2538 // Outcome recommend.
2539 $uc3 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get_id()));
2540 $ev3 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc3->get_id()));
2542 $this->assertEquals(null, $uc3->get_grade());
2543 $this->assertEquals(null, $uc3->get_proficiency());
2544 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc3->get_status());
2546 $this->assertEquals('evidence_coursecompleted', $ev3->get_descidentifier());
2547 $this->assertEquals('tool_lp', $ev3->get_desccomponent());
2548 $this->assertEquals($course->shortname, $ev3->get_desca());
2549 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev3->get_url());
2550 $this->assertEquals(null, $ev3->get_grade());
2551 $this->assertEquals($coursectx->id, $ev3->get_contextid());
2552 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev3->get_action());
2553 $this->assertEquals(null, $ev3->get_actionuserid());
2555 // Outcome complete.
2556 $uc4 = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4->get_id()));
2557 $ev4 = \core_competency\evidence::get_record(array('usercompetencyid' => $uc4->get_id()));
2559 $this->assertEquals(3, $uc4->get_grade());
2560 $this->assertEquals(1, $uc4->get_proficiency());
2561 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc4->get_status());
2563 $this->assertEquals('evidence_coursecompleted', $ev4->get_descidentifier());
2564 $this->assertEquals('tool_lp', $ev4->get_desccomponent());
2565 $this->assertEquals($course->shortname, $ev4->get_desca());
2566 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev4->get_url());
2567 $this->assertEquals(3, $ev4->get_grade());
2568 $this->assertEquals($coursectx->id, $ev4->get_contextid());
2569 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $ev4->get_action());
2570 $this->assertEquals(null, $ev4->get_actionuserid());
2573 public function test_list_course_modules_using_competency() {
2576 $this->resetAfterTest(true);
2577 $dg = $this->getDataGenerator();
2578 $lpg = $dg->get_plugin_generator('core_competency');
2579 $u1 = $dg->create_user();
2580 $u2 = $dg->create_user();
2581 $course = $dg->create_course();
2582 $course2 = $dg->create_course();
2584 $this->setAdminUser();
2585 $f = $lpg->create_framework();
2586 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
2587 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
2588 $cc = api::add_competency_to_course($course->id, $c->get_id());
2589 $cc2 = api::add_competency_to_course($course->id, $c2->get_id());
2591 // First check we get an empty list when there are no links.
2592 $expected = array();
2593 $result = api::list_course_modules_using_competency($c->get_id(), $course->id);
2594 $this->assertEquals($expected, $result);
2596 $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
2597 $page = $pagegenerator->create_instance(array('course' => $course->id));
2599 $cm = get_coursemodule_from_instance('page', $page->id);
2600 // Add a link and list again.
2601 $ccm = api::add_competency_to_course_module($cm, $c->get_id());
2602 $expected = array($cm->id);
2603 $result = api::list_course_modules_using_competency($c->get_id(), $course->id);
2604 $this->assertEquals($expected, $result);
2606 // Check a different course.
2607 $expected = array();
2608 $result = api::list_course_modules_using_competency($c->get_id(), $course2->id);
2609 $this->assertEquals($expected, $result);
2611 // Remove the link and check again.
2612 $result = api::remove_competency_from_course_module($cm, $c->get_id());
2614 $this->assertEquals($expected, $result);
2615 $expected = array();
2616 $result = api::list_course_modules_using_competency($c->get_id(), $course->id);
2617 $this->assertEquals($expected, $result);
2620 api::add_competency_to_course_module($cm, $c->get_id());
2621 api::add_competency_to_course_module($cm, $c2->get_id());
2622 $result = api::list_course_module_competencies_in_course_module($cm->id);
2623 $this->assertEquals($result[0]->get_competencyid(), $c->get_id());
2624 $this->assertEquals($result[1]->get_competencyid(), $c2->get_id());
2627 api::reorder_course_module_competency($cm, $c->get_id(), $c2->get_id());
2628 $result = api::list_course_module_competencies_in_course_module($cm->id);
2629 $this->assertEquals($result[0]->get_competencyid(), $c2->get_id());
2630 $this->assertEquals($result[1]->get_competencyid(), $c->get_id());
2632 // And re-order again.
2633 api::reorder_course_module_competency($cm, $c->get_id(), $c2->get_id());
2634 $result = api::list_course_module_competencies_in_course_module($cm->id);
2635 $this->assertEquals($result[0]->get_competencyid(), $c->get_id());
2636 $this->assertEquals($result[1]->get_competencyid(), $c2->get_id());
2640 * Test update ruleoutcome for course_competency.
2642 public function test_set_ruleoutcome_course_competency() {
2643 $this->resetAfterTest(true);
2644 $dg = $this->getDataGenerator();
2645 $lpg = $dg->get_plugin_generator('core_competency');
2646 $u1 = $dg->create_user();
2647 $u2 = $dg->create_user();
2648 $course = $dg->create_course();
2650 $this->setAdminUser();
2651 $f = $lpg->create_framework();
2652 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
2653 $cc = api::add_competency_to_course($course->id, $c->get_id());
2655 // Check record was created with default rule value Evidence.
2656 $this->assertEquals(1, \core_competency\course_competency::count_records());
2657 $recordscc = api::list_course_competencies($course->id);
2658 $this->assertEquals(\core_competency\course_competency::OUTCOME_EVIDENCE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
2660 // Check ruleoutcome value is updated to None.
2661 $this->assertTrue(api::set_course_competency_ruleoutcome($recordscc[0]['coursecompetency']->get_id(),
2662 \core_competency\course_competency::OUTCOME_NONE));
2663 $recordscc = api::list_course_competencies($course->id);
2664 $this->assertEquals(\core_competency\course_competency::OUTCOME_NONE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
2668 * Test validation on grade on user_competency.
2670 public function test_validate_grade_in_user_competency() {
2673 $this->resetAfterTest(true);
2674 $this->setAdminUser();
2675 $dg = $this->getDataGenerator();
2676 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2677 $user = $dg->create_user();
2679 $dg->create_scale(array("id" => "1", "scale" => "value1, value2"));
2680 $dg->create_scale(array("id" => "2", "scale" => "value3, value4, value5, value6"));
2682 $scaleconfiguration1 = '[{"scaleid":"1"},{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
2683 '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
2684 $scaleconfiguration2 = '[{"scaleid":"2"},{"name":"value3","id":1,"scaledefault":1,"proficient":0},'
2685 . '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
2687 // Create a framework with scale configuration1.
2690 'scaleconfiguration' => $scaleconfiguration1
2692 $framework = $lpg->create_framework($frm);
2693 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2695 // Create competency with its own scale configuration.
2696 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
2698 'scaleconfiguration' => $scaleconfiguration2
2701 // Detecte invalid grade in competency using its framework competency scale.
2703 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get_id(),
2704 'proficiency' => true, 'grade' => 3 ));
2705 $usercompetency->create();
2706 $this->fail('Invalid grade not detected in framework scale');
2707 } catch (\core_competency\invalid_persistent_exception $e) {
2708 $this->assertTrue(true);
2711 // Detecte invalid grade in competency using its own scale.
2713 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get_id(),
2714 'proficiency' => true, 'grade' => 5 ));
2715 $usercompetency->create();
2716 $this->fail('Invalid grade not detected in competency scale');
2717 } catch (\core_competency\invalid_persistent_exception $e) {
2718 $this->assertTrue(true);
2721 // Accept valid grade in competency using its framework competency scale.
2723 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get_id(),
2724 'proficiency' => true, 'grade' => 1 ));
2725 $usercompetency->create();
2726 $this->assertTrue(true);
2727 } catch (\core_competency\invalid_persistent_exception $e) {
2728 $this->fail('Valide grade rejected in framework scale');
2731 // Accept valid grade in competency using its framework competency scale.
2733 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get_id(),
2734 'proficiency' => true, 'grade' => 4 ));
2735 $usercompetency->create();
2736 $this->assertTrue(true);
2737 } catch (\core_competency\invalid_persistent_exception $e) {
2738 $this->fail('Valide grade rejected in competency scale');
2743 * Test when adding competency that belong to hidden framework to plan/template/course.
2745 public function test_hidden_framework() {
2746 $this->resetAfterTest(true);
2747 $this->setAdminUser();
2748 $dg = $this->getDataGenerator();
2749 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2750 $user = $dg->create_user();
2753 $cat1 = $dg->create_category();
2754 $course = $dg->create_course(array('category' => $cat1->id));
2755 // Create a template.
2756 $template = $lpg->create_template();
2758 $plan = $lpg->create_plan(array('userid' => $user->id));
2760 // Create a hidden framework.
2764 $framework = $lpg->create_framework($frm);
2765 $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2767 // Linking competency that belong to hidden framework to course.
2769 api::add_competency_to_course($course->id, $competency->get_id());
2770 $this->fail('A competency belonging to hidden framework can not be linked to course');
2771 } catch (coding_exception $e) {
2772 $this->assertTrue(true);
2775 // Adding competency that belong to hidden framework to template.
2777 api::add_competency_to_template($template->get_id(), $competency->get_id());
2778 $this->fail('A competency belonging to hidden framework can not be added to template');
2779 } catch (coding_exception $e) {
2780 $this->assertTrue(true);
2783 // Adding competency that belong to hidden framework to plan.
2785 api::add_competency_to_plan($plan->get_id(), $competency->get_id());
2786 $this->fail('A competency belonging to hidden framework can not be added to plan');
2787 } catch (coding_exception $e) {
2788 $this->assertTrue(true);
2793 * Test when using hidden template in plan/cohort.
2795 public function test_hidden_template() {
2796 $this->resetAfterTest(true);
2797 $this->setAdminUser();
2798 $dg = $this->getDataGenerator();
2799 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2800 $user = $dg->create_user();
2803 $cohort = $dg->create_cohort();
2804 // Create a hidden template.
2805 $template = $lpg->create_template(array('visible' => false));
2807 // Can not link hidden template to plan.
2809 api::create_plan_from_template($template->get_id(), $user->id);
2810 $this->fail('Can not link a hidden template to plan');
2811 } catch (coding_exception $e) {
2812 $this->assertTrue(true);
2815 // Can associate hidden template to cohort.
2816 $templatecohort = api::create_template_cohort($template->get_id(), $cohort->id);
2817 $this->assertInstanceOf('\core_competency\template_cohort', $templatecohort);
2821 * Test that completed plan created form a template does not change when template is modified.
2823 public function test_completed_plan_doesnot_change() {
2826 $this->resetAfterTest(true);
2827 $this->setAdminUser();
2828 $dg = $this->getDataGenerator();
2829 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2830 $user = $dg->create_user();
2832 // Create a framework and assign competencies.
2833 $framework = $lpg->create_framework();
2834 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2835 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2836 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2837 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2839 // Create template and assign competencies.
2840 $tp = $lpg->create_template();
2841 $tpc1 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c1->get_id()));
2842 $tpc2 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c2->get_id()));
2843 $tpc3 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c3->get_id()));
2845 // Create a plan form template and change it status to complete.
2846 $plan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tp->get_id()));
2847 api::complete_plan($plan);
2849 // Check user competency plan created correctly.
2850 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
2851 $ucp = \core_competency\user_competency_plan::get_records();
2852 $this->assertEquals($ucp[0]->get_competencyid(), $c1->get_id());
2853 $this->assertEquals($ucp[1]->get_competencyid(), $c2->get_id());
2854 $this->assertEquals($ucp[2]->get_competencyid(), $c3->get_id());
2856 // Add and remove a competency from the template.
2857 api::add_competency_to_template($tp->get_id(), $c4->get_id());
2858 api::remove_competency_from_template($tp->get_id(), $c1->get_id());
2860 // Check that user competency plan did not change.
2861 $competencies = $plan->get_competencies();
2862 $this->assertEquals(3, count($competencies));
2863 $ucp1 = array($c1->get_id(), $c2->get_id(), $c3->get_id());
2865 foreach ($competencies as $id => $cmp) {
2868 $this->assertEquals(0, count(array_diff($ucp1, $ucp2)));
2871 protected function setup_framework_for_reset_rules_tests() {
2872 $this->resetAfterTest(true);
2873 $dg = $this->getDataGenerator();
2874 $lpg = $dg->get_plugin_generator('core_competency');
2876 $this->setAdminUser();
2877 $f1 = $lpg->create_framework();
2878 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2879 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2880 $c1a1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a->get_id()));
2881 $c1a1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a1->get_id()));
2882 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2883 $c1b1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
2884 $c1b1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b1->get_id()));
2885 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2886 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2888 $c1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2889 $c1->set_ruletype('core_competency\\competency_rule_all');
2891 $c1a->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2892 $c1a->set_ruletype('core_competency\\competency_rule_all');
2894 $c1a1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2895 $c1a1->set_ruletype('core_competency\\competency_rule_all');
2897 $c1b->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2898 $c1b->set_ruletype('core_competency\\competency_rule_all');
2900 $c2->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2901 $c2->set_ruletype('core_competency\\competency_rule_all');
2918 public function test_moving_competency_reset_rules_updown() {
2919 $data = $this->setup_framework_for_reset_rules_tests();
2922 $c1a = $data['c1a'];
2923 $c1a1 = $data['c1a1'];
2924 $c1a1a = $data['c1a1a'];
2925 $c1b = $data['c1b'];
2926 $c1b1 = $data['c1b1'];
2927 $c1b1a = $data['c1b1a'];
2929 $c2a = $data['c2a'];
2931 // Moving up and down doesn't change anything.
2932 api::move_down_competency($c1a->get_id());
2936 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2937 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2938 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2939 api::move_up_competency($c1a->get_id());
2943 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2944 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2945 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2948 public function test_moving_competency_reset_rules_parent() {
2949 $data = $this->setup_framework_for_reset_rules_tests();
2952 $c1a = $data['c1a'];
2953 $c1a1 = $data['c1a1'];
2954 $c1a1a = $data['c1a1a'];
2955 $c1b = $data['c1b'];
2956 $c1b1 = $data['c1b1'];
2957 $c1b1a = $data['c1b1a'];
2959 $c2a = $data['c2a'];
2961 // Moving out of parent will reset the parent, and the destination.
2962 api::set_parent_competency($c1a->get_id(), $c1b->get_id());
2968 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
2969 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2970 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2971 $this->assertEquals(competency::OUTCOME_NONE, $c1b->get_ruleoutcome());
2972 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2975 public function test_moving_competency_reset_rules_totoplevel() {
2976 $data = $this->setup_framework_for_reset_rules_tests();
2979 $c1a = $data['c1a'];
2980 $c1a1 = $data['c1a1'];
2981 $c1a1a = $data['c1a1a'];
2982 $c1b = $data['c1b'];
2983 $c1b1 = $data['c1b1'];
2984 $c1b1a = $data['c1b1a'];
2986 $c2a = $data['c2a'];
2988 // Moving to top level only affects the initial parent.
2989 api::set_parent_competency($c1a1->get_id(), 0);
2995 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2996 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get_ruleoutcome());
2997 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2998 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2999 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
3002 public function test_moving_competency_reset_rules_fromtoplevel() {
3003 $data = $this->setup_framework_for_reset_rules_tests();
3006 $c1a = $data['c1a'];
3007 $c1a1 = $data['c1a1'];
3008 $c1a1a = $data['c1a1a'];
3009 $c1b = $data['c1b'];
3010 $c1b1 = $data['c1b1'];
3011 $c1b1a = $data['c1b1a'];
3013 $c2a = $data['c2a'];
3015 // Moving from top level only affects the destination parent.
3016 api::set_parent_competency($c2->get_id(), $c1a1->get_id());
3022 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
3023 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
3024 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get_ruleoutcome());
3025 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
3026 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
3029 public function test_moving_competency_reset_rules_child() {
3030 $data = $this->setup_framework_for_reset_rules_tests();
3033 $c1a = $data['c1a'];
3034 $c1a1 = $data['c1a1'];
3035 $c1a1a = $data['c1a1a'];
3036 $c1b = $data['c1b'];
3037 $c1b1 = $data['c1b1'];
3038 $c1b1a = $data['c1b1a'];
3040 $c2a = $data['c2a'];
3042 // Moving to a child of self resets self, parent and destination.
3043 api::set_parent_competency($c1a->get_id(), $c1a1->get_id());
3049 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
3050 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get_ruleoutcome());
3051 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get_ruleoutcome());
3052 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
3053 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
3056 public function test_create_competency_reset_rules() {
3057 $data = $this->setup_framework_for_reset_rules_tests();
3060 $c1a = $data['c1a'];
3061 $c1a1 = $data['c1a1'];
3062 $c1a1a = $data['c1a1a'];
3063 $c1b = $data['c1b'];
3064 $c1b1 = $data['c1b1'];
3065 $c1b1a = $data['c1b1a'];
3067 $c2a = $data['c2a'];
3069 // Adding a new competency resets the rule of its parent.
3070 api::create_competency((object) array('shortname' => 'A', 'parentid' => $c1->get_id(), 'idnumber' => 'A',
3071 'competencyframeworkid' => $f1->get_id()));
3077 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
3078 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
3079 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
3080 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
3081 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
3084 public function test_delete_competency_reset_rules() {
3085 $data = $this->setup_framework_for_reset_rules_tests();
3088 $c1a = $data['c1a'];
3089 $c1a1 = $data['c1a1'];
3090 $c1a1a = $data['c1a1a'];
3091 $c1b = $data['c1b'];
3092 $c1b1 = $data['c1b1'];
3093 $c1b1a = $data['c1b1a'];
3095 $c2a = $data['c2a'];
3097 // Deleting a competency resets the rule of its parent.
3098 api::delete_competency($c1a->get_id());
3102 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
3103 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
3104 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
3107 public function test_template_has_related_data() {
3108 $this->resetAfterTest(true);
3109 $this->setAdminUser();
3111 $dg = $this->getDataGenerator();
3112 $user = $dg->create_user();
3113 $lpg = $dg->get_plugin_generator('core_competency');
3114 $tpl1 = $lpg->create_template();
3115 $tpl2 = $lpg->create_template();
3117 // Create plans for first template.
3119 $plan1 = $lpg->create_plan(array('templateid' => $tpl1->get_id(), 'userid' => $user->id,
3120 'name' => 'Not good name', 'duedate' => $time + 3600, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
3122 $this->assertTrue(api::template_has_related_data($tpl1->get_id()));
3123 $this->assertFalse(api::template_has_related_data($tpl2->get_id()));
3127 public function test_delete_template_delete_plans() {
3128 $this->resetAfterTest(true);
3129 $this->setAdminUser();
3131 $dg = $this->getDataGenerator();
3132 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
3134 $u1 = $dg->create_user();
3135 $f = $lpg->create_framework();
3136 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
3137 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
3139 $tpl = $lpg->create_template();
3141 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id(),
3143 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2->get_id(),
3146 $p1 = $lpg->create_plan(array('templateid' => $tpl->get_id(), 'userid' => $u1->id));
3149 $this->assertTrue(\core_competency\template::record_exists($tpl->get_id()));
3150 $this->assertEquals(2, \core_competency\template_competency::count_competencies($tpl->get_id()));
3151 $this->assertEquals(1, count(\core_competency\plan::get_records(array('templateid' => $tpl->get_id()))));
3153 $result = api::delete_template($tpl->get_id(), true);
3154 $this->assertTrue($result);
3156 // Check that the template does not exist anymore.
3157 $this->assertFalse(\core_competency\template::record_exists($tpl->get_id()));
3159 // Check that associated competencies are also deleted.
3160 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get_id()));
3162 // Check that associated plan are also deleted.
3163 $this->assertEquals(0, count(\core_competency\plan::get_records(array('templateid' => $tpl->get_id()))));
3166 public function test_delete_template_unlink_plans() {
3167 $this->resetAfterTest(true);
3168 $this->setAdminUser();
3170 $dg = $this->getDataGenerator();
3171 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
3173 $u1 = $dg->create_user();
3174 $f = $lpg->create_framework();
3175 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
3176 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
3178 $tpl = $lpg->create_template();
3180 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id(),
3182 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2->get_id(),
3185 $p1 = $lpg->create_plan(array('templateid' => $tpl->get_id(), 'userid' => $u1->id));
3188 $this->assertTrue(\core_competency\template::record_exists($tpl->get_id()));
3189 $this->assertEquals(2, \core_competency\template_competency::count_competencies($tpl->get_id()));
3190 $this->assertEquals(1, count(\core_competency\plan::get_records(array('templateid' => $tpl->get_id()))));
3192 $result = api::delete_template($tpl->get_id(), false);
3193 $this->assertTrue($result);
3195 // Check that the template does not exist anymore.
3196 $this->assertFalse(\core_competency\template::record_exists($tpl->get_id()));
3198 // Check that associated competencies are also deleted.
3199 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get_id()));
3201 // Check that associated plan still exist but unlink from template.
3202 $plans = \core_competency\plan::get_records(array('id' => $p1->get_id()));
3203 $this->assertEquals(1, count($plans));
3204 $this->assertEquals($plans[0]->get_origtemplateid(), $tpl->get_id());
3205 $this->assertNull($plans[0]->get_templateid());
3208 public function test_delete_competency() {
3209 $this->resetAfterTest(true);
3210 $dg = $this->getDataGenerator();
3211 $lpg = $dg->get_plugin_generator('core_competency');
3212 $this->setAdminUser();
3214 $u1 = $dg->create_user();
3216 $f1 = $lpg->create_framework();
3217 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
3218 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
3219 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
3220 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a->get_id()));
3221 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
3222 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
3224 // Set rules on parent competency.
3225 $c1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
3226 $c1->set_ruletype('core_competency\\competency_rule_all');
3229 // If we delete competeny, the related competencies relations and evidences should be deleted.
3230 // Create related competencies using one of c1a competency descendants.
3231 $rc = $lpg->create_related_competency(array(
3232 'competencyid' => $c2->get_id(),
3233 'relatedcompetencyid' => $c11b->get_id()
3235 $this->assertEquals($c11b->get_id(), $rc->get_relatedcompetencyid());
3237 // Creating a standard evidence with minimal information.
3238 $uc2 = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c11b->get_id()));
3239 $evidence = $lpg->create_evidence(array('usercompetencyid' => $uc2->get_id()));
3240 $this->assertEquals($uc2->get_id(), $evidence->get_usercompetencyid());
3243 $this->assertTrue(api::delete_competency($c1a->get_id()));
3244 $this->assertFalse(competency::record_exists($c1a->get_id()));
3246 // Check that on delete, we reset the rule on parent competency.
3248 $this->assertNull($c1->get_ruletype());
3249 $this->assertNull($c1->get_ruletype());
3250 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
3252 // Check that descendants were also deleted.
3253 $this->assertFalse(competency::record_exists($c1b->get_id()));
3254 $this->assertFalse(competency::record_exists($c11b->get_id()));
3255 $this->assertFalse(competency::record_exists($c12b->get_id()));
3257 // Check if evidence are also deleted.
3258 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get_id())));
3260 // Check if related conpetency relation is deleted.
3261 $this->assertEquals(0, count(api::list_related_competencies($c2->get_id())));
3263 // Delete a simple competency.
3264 $this->assertTrue(api::delete_competency($c2->get_id()));
3265 $this->assertFalse(competency::record_exists($c2->get_id()));
3268 public function test_delete_competency_used_in_plan() {
3269 $this->resetAfterTest(true);
3270 $dg = $this->getDataGenerator();
3271 $lpg = $dg->get_plugin_generator('core_competency');
3272 $this->setAdminUser();
3274 $u1 = $dg->create_user();