MDL-53700 competency: Migrating tests to core
[moodle.git] / competency / tests / api_test.php
CommitLineData
f610a957
FM
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * API tests.
19 *
e0b9ba28 20 * @package core_competency
f610a957
FM
21 * @copyright 2015 Frédéric Massart - FMCorz.net
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26global $CFG;
27
767f66c0 28use core_competency\api;
67bc0eaf
FM
29use core_competency\competency;
30use core_competency\competency_framework;
31use core_competency\course_competency_settings;
32use core_competency\evidence;
33use core_competency\user_competency;
34use core_competency\plan;
f610a957
FM
35
36/**
37 * API tests.
38 *
e0b9ba28 39 * @package core_competency
f610a957
FM
40 * @copyright 2015 Frédéric Massart - FMCorz.net
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 */
e0b9ba28 43class core_competency_api_testcase extends advanced_testcase {
f610a957
FM
44
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));
f0da26a4 51 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
f610a957
FM
52
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();
57
58 $expected = array($cat1ctx->id => $cat1ctx);
f0da26a4 59 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
f610a957
FM
60
61 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
f0da26a4 62 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
f610a957
FM
63
64 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
f0da26a4 65 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
f610a957
FM
66 }
67
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));
f0da26a4 75 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
f610a957
FM
76
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();
81
82 $roleallow = create_role('Allow', 'allow', 'Allow read');
b90e2205 83 assign_capability('moodle/competency:competencyview', CAP_ALLOW, $roleallow, $sysctx->id);
f610a957
FM
84 role_assign($roleallow, $user->id, $sysctx->id);
85
86 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
b90e2205 87 assign_capability('moodle/competency:competencyview', CAP_PROHIBIT, $roleprevent, $sysctx->id);
f610a957
FM
88 role_assign($roleprevent, $user->id, $cat2ctx->id);
89
90 accesslib_clear_all_caches_for_unit_testing();
91 $this->setUser($user);
b90e2205 92 $this->assertFalse(has_capability('moodle/competency:competencyview', $cat2ctx));
f610a957 93
b90e2205 94 $requiredcap = array('moodle/competency:competencyview');
f610a957
FM
95
96 $expected = array();
f0da26a4 97 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
f610a957
FM
98
99 $expected = array($cat1ctx->id => $cat1ctx);
f0da26a4 100 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
f610a957
FM
101
102 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
f0da26a4 103 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
f610a957 104 }
f0da26a4
FM
105
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.
113
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();
118
119 $expected = array($cat1ctx->id => $cat1ctx);
120 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
121
122 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
123 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
124
125 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
126 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
127 }
128
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.
137
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();
142
143 $roleallow = create_role('Allow', 'allow', 'Allow read');
b90e2205 144 assign_capability('moodle/competency:templateview', CAP_ALLOW, $roleallow, $sysctx->id);
f0da26a4
FM
145 role_assign($roleallow, $user->id, $sysctx->id);
146
147 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
b90e2205 148 assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $roleprevent, $sysctx->id);
f0da26a4
FM
149 role_assign($roleprevent, $user->id, $cat2ctx->id);
150
151 accesslib_clear_all_caches_for_unit_testing();
152 $this->setUser($user);
b90e2205 153 $this->assertFalse(has_capability('moodle/competency:templateview', $cat2ctx));
f0da26a4 154
b90e2205 155 $requiredcap = array('moodle/competency:templateview');
f0da26a4
FM
156
157 $expected = array();
158 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
159
160 $expected = array($cat1ctx->id => $cat1ctx);
161 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
162
163 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
164 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
165 }
166
ec324dc6
FM
167 /**
168 * Test updating a template.
169 */
170 public function test_update_template() {
171 $cat = $this->getDataGenerator()->create_category();
172 $this->resetAfterTest(true);
173 $this->setAdminUser();
174
175 $syscontext = context_system::instance();
176 $template = api::create_template((object) array('shortname' => 'testing', 'contextid' => $syscontext->id));
177
178 $this->assertEquals('testing', $template->get_shortname());
179 $this->assertEquals($syscontext->id, $template->get_contextid());
180
181 // Simple update.
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());
185
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)));
189 }
190
b3979696
IT
191 /**
192 * Test listing framework with order param.
193 */
194 public function test_list_frameworks() {
195 $this->resetAfterTest(true);
196 $this->setAdminUser();
922634d3 197 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
b3979696
IT
198
199 // Create a list of frameworks.
bf61cd0c 200 $framework1 = $lpg->create_framework(array(
0fe5aac7
FM
201 'shortname' => 'shortname_alpha',
202 'idnumber' => 'idnumber_cinnamon',
bf61cd0c
FM
203 'description' => 'description',
204 'descriptionformat' => FORMAT_HTML,
205 'visible' => true,
206 'contextid' => context_system::instance()->id
207 ));
208
209 $framework2 = $lpg->create_framework(array(
0fe5aac7
FM
210 'shortname' => 'shortname_beetroot',
211 'idnumber' => 'idnumber_apple',
bf61cd0c
FM
212 'description' => 'description',
213 'descriptionformat' => FORMAT_HTML,
214 'visible' => true,
215 'contextid' => context_system::instance()->id
216 ));
217
218 $framework3 = $lpg->create_framework(array(
0fe5aac7
FM
219 'shortname' => 'shortname_crisps',
220 'idnumber' => 'idnumber_beer',
bf61cd0c
FM
221 'description' => 'description',
222 'descriptionformat' => FORMAT_HTML,
0fe5aac7 223 'visible' => false,
bf61cd0c
FM
224 'contextid' => context_system::instance()->id
225 ));
b3979696
IT
226
227 // Get frameworks list order by shortname desc.
228 $result = api::list_frameworks('shortname', 'DESC', null, 3, context_system::instance());
229
1896274f
FM
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());
b3979696
IT
236
237 // Get frameworks list order by idnumber asc.
238 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance());
239
1896274f
FM
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());
0fe5aac7
FM
246
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());
254
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());
260
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);
264
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());
270
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());
b3979696
IT
278 }
279
c61db7bb
IT
280 /**
281 * Test duplicate a framework.
282 */
283 public function test_duplicate_framework() {
922634d3 284 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
c61db7bb
IT
285 $this->resetAfterTest(true);
286 $this->setAdminUser();
287
288 $syscontext = context_system::instance();
289 $params = array(
290 'shortname' => 'shortname_a',
291 'idnumber' => 'idnumber_c',
292 'description' => 'description',
293 'descriptionformat' => FORMAT_HTML,
294 'visible' => true,
295 'contextid' => $syscontext->id
296 );
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()));
4c4a8d41
IT
302 $competency41 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
303 'parentid' => $competency4->get_id())
304 );
305 $competency42 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
306 'parentid' => $competency4->get_id())
307 );
c61db7bb
IT
308 $competencyidnumbers = array($competency1->get_idnumber(),
309 $competency2->get_idnumber(),
310 $competency3->get_idnumber(),
4c4a8d41
IT
311 $competency4->get_idnumber(),
312 $competency41->get_idnumber(),
313 $competency42->get_idnumber()
c61db7bb
IT
314 );
315
4c4a8d41
IT
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),
321 )
322 ));
67bc0eaf
FM
323 $competency4->set_ruletype('core_competency\competency_rule_points');
324 $competency4->set_ruleoutcome(\core_competency\competency::OUTCOME_EVIDENCE);
4c4a8d41
IT
325 $competency4->set_ruleconfig($config);
326 $competency4->update();
327
c61db7bb
IT
328 api::add_related_competency($competency1->get_id(), $competency2->get_id());
329 api::add_related_competency($competency3->get_id(), $competency4->get_id());
330
331 $frameworkduplicated1 = api::duplicate_framework($framework->get_id());
332 $frameworkduplicated2 = api::duplicate_framework($framework->get_id());
333
334 $this->assertEquals($framework->get_idnumber().'_1', $frameworkduplicated1->get_idnumber());
335 $this->assertEquals($framework->get_idnumber().'_2', $frameworkduplicated2->get_idnumber());
336
337 $competenciesfr1 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated1->get_id()));
338 $competenciesfr2 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated2->get_id()));
339
340 $competencyidsfr1 = array();
341 $competencyidsfr2 = array();
342
343 foreach ($competenciesfr1 as $cmp) {
344 $competencyidsfr1[] = $cmp->get_idnumber();
345 }
346 foreach ($competenciesfr2 as $cmp) {
347 $competencyidsfr2[] = $cmp->get_idnumber();
348 }
349
350 $this->assertEmpty(array_diff($competencyidsfr1, $competencyidnumbers));
351 $this->assertEmpty(array_diff($competencyidsfr2, $competencyidnumbers));
4c4a8d41
IT
352 $this->assertCount(6, $competenciesfr1);
353 $this->assertCount(6, $competenciesfr2);
c61db7bb
IT
354
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());
5a4ee001 361
4c4a8d41
IT
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()
366 ));
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']));
9a325eda 372 $competencyidsrules = array();
4c4a8d41
IT
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])));
9a325eda 376 $competencyidsrules[] = $value['id'];
4c4a8d41 377 }
9a325eda 378 $this->assertTrue($competency4duplicated->is_parent_of($competencyidsrules));
5a4ee001 379
20e75095
IT
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);
386
c61db7bb
IT
387 }
388
58405003
IT
389 /**
390 * Test update plan.
391 */
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();
399
400 $syscontext = context_system::instance();
401
402 // Creating specific roles.
403 $manageowndraftrole = $dg->create_role(array(
404 'name' => 'User manage own draft',
405 'shortname' => 'manage-own-draft'
406 ));
407 $manageownrole = $dg->create_role(array(
408 'name' => 'User manage own',
409 'shortname' => 'manage-own'
410 ));
411 $managedraftrole = $dg->create_role(array(
412 'name' => 'User manage draft',
413 'shortname' => 'manage-draft'
414 ));
415 $managerole = $dg->create_role(array(
416 'name' => 'User manage',
417 'shortname' => 'manage'
418 ));
419
b90e2205
FM
420 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
421 assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
58405003 422
b90e2205
FM
423 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
424 assign_capability('moodle/competency:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
58405003 425
b90e2205
FM
426 assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
427 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
58405003 428
b90e2205
FM
429 assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
430 assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
58405003
IT
431
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);
436
437 // Create first learning plan with user create draft.
438 $this->setUser($usermanageowndraft);
439 $plan = array (
440 'name' => 'plan own draft',
441 'description' => 'plan own draft',
442 'userid' => $usermanageowndraft->id
443 );
444 $plan = api::create_plan((object)$plan);
445 $record = $plan->to_record();
446 $record->name = 'plan own draft modified';
447
448 // Check if user create draft can edit the plan name.
449 $plan = api::update_plan($record);
67bc0eaf 450 $this->assertInstanceOf('\core_competency\plan', $plan);
58405003 451
3c230247 452 // The status cannot be changed in this method.
67bc0eaf 453 $record->status = \core_competency\plan::STATUS_ACTIVE;
58405003
IT
454 try {
455 $plan = api::update_plan($record);
3c230247
FM
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());
58405003
IT
459 }
460
461 // Test when user with manage own plan capability try to edit other user plan.
67bc0eaf 462 $record->status = \core_competency\plan::STATUS_DRAFT;
58405003
IT
463 $record->name = 'plan create draft modified 2';
464 $this->setUser($usermanageown);
465 try {
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);
470 }
471
472 // User with manage plan capability cannot edit the other user plans with status draft.
473 $this->setUser($usermanage);
3c230247 474 $record->name = 'plan create draft modified 3';
58405003
IT
475 try {
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);
480 }
481
482 // User with manage draft capability can edit other user's learning plan if the status is draft.
483 $this->setUser($usermanagedraft);
67bc0eaf 484 $record->status = \core_competency\plan::STATUS_DRAFT;
58405003
IT
485 $record->name = 'plan manage draft modified 3';
486 $plan = api::update_plan($record);
67bc0eaf 487 $this->assertInstanceOf('\core_competency\plan', $plan);
58405003
IT
488
489 // User with manage plan capability can create/edit learning plan if status is active/complete.
490 $this->setUser($usermanage);
491 $plan = array (
492 'name' => 'plan create',
493 'description' => 'plan create',
494 'userid' => $usermanage->id,
67bc0eaf 495 'status' => \core_competency\plan::STATUS_ACTIVE
58405003
IT
496 );
497 $plan = api::create_plan((object)$plan);
5bfab685
FM
498
499 // Silently transition to complete status to avoid errors about transitioning to complete.
67bc0eaf 500 $plan->set_status(\core_competency\plan::STATUS_COMPLETE);
5bfab685
FM
501 $plan->update();
502
58405003
IT
503 $record = $plan->to_record();
504 $record->name = 'plan create own modified';
d805cc37
IT
505 try {
506 api::update_plan($record);
507 $this->fail('Completed plan can not be edited');
508 } catch (coding_exception $e) {
509 $this->assertTrue(true);
510 }
58405003
IT
511 }
512
2388d46d
FM
513 public function test_create_plan_from_template() {
514 $this->resetAfterTest(true);
515 $this->setAdminUser();
516
517 $u1 = $this->getDataGenerator()->create_user();
922634d3 518 $tpl = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_template();
2388d46d
FM
519
520 // Creating a new plan.
521 $plan = api::create_plan_from_template($tpl, $u1->id);
522 $record = $plan->to_record();
67bc0eaf
FM
523 $this->assertInstanceOf('\core_competency\plan', $plan);
524 $this->assertTrue(\core_competency\plan::record_exists($plan->get_id()));
2388d46d
FM
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());
528
529 // Creating a plan that already exists.
530 $plan = api::create_plan_from_template($tpl, $u1->id);
531 $this->assertFalse($plan);
532
533 // Check that api::create_plan cannot be used.
534 $this->setExpectedException('coding_exception');
535 unset($record->id);
536 $plan = api::create_plan($record);
537 }
538
4de877eb
FM
539 public function test_update_plan_based_on_template() {
540 $this->resetAfterTest(true);
541 $dg = $this->getDataGenerator();
922634d3 542 $lpg = $dg->get_plugin_generator('core_competency');
4de877eb
FM
543 $u1 = $dg->create_user();
544 $u2 = $dg->create_user();
545
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));
551
552 try {
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) {
96c2b847 559 // All good.
4de877eb
FM
560 }
561
562 try {
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) {
96c2b847 569 // All good.
4de877eb
FM
570 }
571
572 try {
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) {
96c2b847 579 // All good.
4de877eb
FM
580 }
581 }
582
6d2c2e86
FM
583 public function test_unlink_plan_from_template() {
584 $this->resetAfterTest(true);
585 $dg = $this->getDataGenerator();
922634d3 586 $lpg = $dg->get_plugin_generator('core_competency');
6d2c2e86
FM
587 $u1 = $dg->create_user();
588 $u2 = $dg->create_user();
589
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()));
596
597 $tpl1 = $lpg->create_template();
598 $tpl2 = $lpg->create_template();
599
600 $tplc1a = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1a->get_id(),
601 'sortorder' => 9));
602 $tplc1b = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1b->get_id(),
603 'sortorder' => 8));
604 $tplc2a = $lpg->create_template_competency(array('templateid' => $tpl2->get_id(), 'competencyid' => $c2a->get_id()));
605
a8902ee2 606 $plan1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_ACTIVE));
6d2c2e86 607 $plan2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => $tpl2->get_id()));
a8902ee2 608 $plan3 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_COMPLETE));
6d2c2e86
FM
609
610 // Check that we have what we expect at this stage.
67bc0eaf
FM
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())));
6d2c2e86
FM
615 $this->assertTrue($plan1->is_based_on_template());
616 $this->assertTrue($plan2->is_based_on_template());
617
618 // Let's do this!
67bc0eaf
FM
619 $tpl1comps = \core_competency\template_competency::list_competencies($tpl1->get_id(), true);
620 $tpl2comps = \core_competency\template_competency::list_competencies($tpl2->get_id(), true);
6d2c2e86
FM
621
622 api::unlink_plan_from_template($plan1);
623
624 $plan1->read();
625 $plan2->read();
626 $this->assertCount(2, $tpl1comps);
627 $this->assertCount(1, $tpl2comps);
67bc0eaf
FM
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())));
6d2c2e86
FM
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());
636
a8902ee2
SG
637 // Check we can unlink draft plan.
638 try {
639 api::unlink_plan_from_template($plan2);
640 } catch (coding_exception $e) {
641 $this->fail('Fail to unlink draft plan.');
642 }
643
644 // Check we can not unlink completed plan.
645 try {
646 api::unlink_plan_from_template($plan3);
647 $this->fail('We can not unlink completed plan.');
648 } catch (coding_exception $e) {
96c2b847 649 // All good.
a8902ee2
SG
650 }
651
6d2c2e86 652 // Even the order remains.
67bc0eaf 653 $plan1comps = \core_competency\plan_competency::list_competencies($plan1->get_id());
6d2c2e86
FM
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());
662 }
663
c7999f6d
FM
664 public function test_update_template_updates_plans() {
665 $this->resetAfterTest(true);
666 $this->setAdminUser();
667
668 $dg = $this->getDataGenerator();
669 $u1 = $dg->create_user();
670 $u2 = $dg->create_user();
922634d3 671 $lpg = $dg->get_plugin_generator('core_competency');
c7999f6d
FM
672 $tpl1 = $lpg->create_template();
673 $tpl2 = $lpg->create_template();
674
c7999f6d
FM
675 // Create plans with data not matching templates.
676 $time = time();
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));
683
684 // Prepare our expectations.
685 $plan1->read();
686 $plan2->read();
687 $plan3->read();
688
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());
704
705 // Update the template without changing critical fields does not update the plans.
706 $data = $tpl1->to_record();
707 $data->visible = 0;
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());
721
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;
a967d2aa 727 $data->duedate = $time + 200;
c7999f6d
FM
728 api::update_template($data);
729 $tpl1->read();
730
731 // Now confirm that the right plans were updated.
732 $plan1->read();
733 $plan2->read();
734 $plan3->read();
735
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());
739
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());
752 }
753
5bfab685
FM
754 /**
755 * Test that the method to complete a plan.
756 */
757 public function test_complete_plan() {
758 global $DB;
759
760 $this->resetAfterTest(true);
761 $this->setAdminUser();
762 $dg = $this->getDataGenerator();
922634d3 763 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
5bfab685
FM
764 $user = $dg->create_user();
765
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()));
d3275795 771 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
5bfab685
FM
772
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));
776
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()));
781
782 $uclist = array(
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 ))
787 );
788
67bc0eaf
FM
789 $this->assertEquals(2, \core_competency\user_competency::count_records());
790 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
5bfab685
FM
791
792 // Change status of the plan to complete.
793 api::complete_plan($plan);
794
795 // Check that user competencies are now in user_competency_plan objects and still in user_competency.
67bc0eaf
FM
796 $this->assertEquals(2, \core_competency\user_competency::count_records());
797 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
5bfab685 798
67bc0eaf 799 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
5bfab685
FM
800
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());
806
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());
812
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());
818
d3275795
SG
819 // Check we can not add competency to completed plan.
820 try {
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) {
96c2b847 824 // All good.
d3275795
SG
825 }
826
827 // Check we can not remove competency to completed plan.
828 try {
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) {
96c2b847 832 // All good.
d3275795
SG
833 }
834
5bfab685
FM
835 // Completing a plan that is completed throws an exception.
836 $this->setExpectedException('coding_exception');
837 api::complete_plan($plan);
838 }
839
3c230247
FM
840 /**
841 * Set-up the workflow data (review, active, ...).
842 *
843 * @return array
844 */
845 protected function setup_workflow_data() {
846 $this->resetAfterTest();
847
848 $dg = $this->getDataGenerator();
849 $user = $dg->create_user();
850 $reviewer = $dg->create_user();
851 $otheruser = $dg->create_user();
852
853 $syscontext = context_system::instance();
854 $userrole = $dg->create_role();
855 $reviewerrole = $dg->create_role();
856 $otheruserrole = $dg->create_role();
857
b90e2205
FM
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);
3c230247
FM
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();
864
922634d3 865 $lpg = $dg->get_plugin_generator('core_competency');
3c230247
FM
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()));
869
870 return array(
871 'dg' => $dg,
872 'lpg' => $lpg,
873 'user' => $user,
874 'reviewer' => $reviewer,
875 'otheruser' => $otheruser,
876 'plan' => $plan,
877 'tplplan' => $tplplan,
878 );
879 }
880
881 /**
882 * Testing requesting the review of a plan.
883 */
884 public function test_plan_request_review() {
885 $data = $this->setup_workflow_data();
96c2b847
FM
886 $dg = $data['dg'];
887 $lpg = $data['lpg'];
888 $user = $data['user'];
889 $reviewer = $data['reviewer'];
890 $otheruser = $data['otheruser'];
891 $plan = $data['plan'];
892 $tplplan = $data['tplplan'];
3c230247
FM
893
894 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
895 $this->assertEquals(plan::STATUS_DRAFT, $tplplan->get_status());
896
897 // Foreign user cannot do anything.
898 $this->setUser($otheruser);
899 try {
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);
904 }
905
906 // Can not change a plan based on a template.
907 $this->setUser($user);
908 try {
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());
913 }
914
915 // Can not send for review when not draft.
916 $this->setUser($user);
917 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
918 try {
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());
923 }
924
925 // Can not send for review when not draft.
926 $this->setUser($user);
927 $plan->set_status(plan::STATUS_ACTIVE);
928 try {
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());
933 }
934
935 // Can not send for review when not draft.
936 $this->setUser($user);
937 $plan->set_status(plan::STATUS_IN_REVIEW);
938 try {
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());
943 }
944
945 // Can not send for review when not draft.
946 $this->setUser($user);
947 $plan->set_status(plan::STATUS_COMPLETE);
948 try {
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());
953 }
954
955 // Sending for review as a reviewer.
956 $this->setUser($reviewer);
957 $plan->set_status(plan::STATUS_DRAFT);
958 try {
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);
963 }
964
965 // Sending for review.
966 $this->setUser($user);
967 api::plan_request_review($plan);
968 $plan->read();
969 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
970
971 // Sending for review by ID.
972 $plan->set_status(plan::STATUS_DRAFT);
973 $plan->update();
974 api::plan_request_review($plan->get_id());
975 $plan->read();
976 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
977 }
978
979 /**
980 * Testing cancelling the review request.
981 */
982 public function test_plan_cancel_review_request() {
983 $data = $this->setup_workflow_data();
96c2b847
FM
984 $dg = $data['dg'];
985 $lpg = $data['lpg'];
986 $user = $data['user'];
987 $reviewer = $data['reviewer'];
988 $otheruser = $data['otheruser'];
989 $plan = $data['plan'];
990 $tplplan = $data['tplplan'];
3c230247
FM
991
992 // Set waiting for review.
993 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
994 $tplplan->update();
995 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
996 $plan->update();
997
998 // Foreign user cannot do anything.
999 $this->setUser($otheruser);
1000 try {
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);
1005 }
1006
1007 // Can not change a plan based on a template.
1008 $this->setUser($user);
1009 try {
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());
1014 }
1015
1016 // Can not cancel review request when not waiting for review.
1017 $this->setUser($user);
1018 $plan->set_status(plan::STATUS_DRAFT);
1019 try {
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());
1024 }
1025
1026 // Can not cancel review request when not waiting for review.
1027 $this->setUser($user);
1028 $plan->set_status(plan::STATUS_IN_REVIEW);
1029 try {
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());
1034 }
1035
1036 // Can not cancel review request when not waiting for review.
1037 $this->setUser($user);
1038 $plan->set_status(plan::STATUS_ACTIVE);
1039 try {
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());
1044 }
1045
1046 // Can not cancel review request when not waiting for review.
1047 $this->setUser($user);
1048 $plan->set_status(plan::STATUS_COMPLETE);
1049 try {
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());
1054 }
1055
1056 // Cancelling as a reviewer.
1057 $this->setUser($reviewer);
1058 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1059 try {
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);
1064 }
1065
1066 // Cancelling review request.
1067 $this->setUser($user);
1068 api::plan_cancel_review_request($plan);
1069 $plan->read();
1070 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1071
1072 // Cancelling review request by ID.
1073 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1074 $plan->update();
1075 api::plan_cancel_review_request($plan->get_id());
1076 $plan->read();
1077 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1078 }
1079
1080 /**
1081 * Testing starting the review.
1082 */
1083 public function test_plan_start_review() {
1084 $data = $this->setup_workflow_data();
96c2b847
FM
1085 $dg = $data['dg'];
1086 $lpg = $data['lpg'];
1087 $user = $data['user'];
1088 $reviewer = $data['reviewer'];
1089 $otheruser = $data['otheruser'];
1090 $plan = $data['plan'];
1091 $tplplan = $data['tplplan'];
3c230247
FM
1092
1093 // Set waiting for review.
1094 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1095 $tplplan->update();
1096 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1097 $plan->update();
1098
1099 // Foreign user cannot do anything.
1100 $this->setUser($otheruser);
1101 try {
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);
1106 }
1107
1108 // Can not change a plan based on a template.
1109 $this->setUser($reviewer);
1110 try {
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());
1115 }
1116
1117 // Can not start a review when not waiting for review.
1118 $this->setUser($reviewer);
1119 $plan->set_status(plan::STATUS_DRAFT);
1120 try {
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());
1125 }
1126
1127 // Can not start a review when not waiting for review.
1128 $this->setUser($reviewer);
1129 $plan->set_status(plan::STATUS_IN_REVIEW);
1130 try {
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());
1135 }
1136
1137 // Can not start a review when not waiting for review.
1138 $this->setUser($reviewer);
1139 $plan->set_status(plan::STATUS_ACTIVE);
1140 try {
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());
1145 }
1146
1147 // Can not start a review when not waiting for review.
1148 $this->setUser($reviewer);
1149 $plan->set_status(plan::STATUS_COMPLETE);
1150 try {
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());
1155 }
1156
1157 // Starting as the owner.
1158 $this->setUser($user);
1159 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1160 try {
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);
1165 }
1166
1167 // Starting review.
1168 $this->setUser($reviewer);
1169 api::plan_start_review($plan);
1170 $plan->read();
1171 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1172 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1173
1174 // Starting review by ID.
1175 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1176 $plan->set_reviewerid(null);
1177 $plan->update();
1178 api::plan_start_review($plan->get_id());
1179 $plan->read();
1180 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1181 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1182 }
1183
1184 /**
1185 * Testing stopping the review.
1186 */
1187 public function test_plan_stop_review() {
1188 $data = $this->setup_workflow_data();
96c2b847
FM
1189 $dg = $data['dg'];
1190 $lpg = $data['lpg'];
1191 $user = $data['user'];
1192 $reviewer = $data['reviewer'];
1193 $otheruser = $data['otheruser'];
1194 $plan = $data['plan'];
1195 $tplplan = $data['tplplan'];
3c230247
FM
1196
1197 // Set waiting for review.
1198 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1199 $tplplan->update();
1200 $plan->set_status(plan::STATUS_IN_REVIEW);
1201 $plan->update();
1202
1203 // Foreign user cannot do anything.
1204 $this->setUser($otheruser);
1205 try {
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);
1210 }
1211
1212 // Can not change a plan based on a template.
1213 $this->setUser($reviewer);
1214 try {
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());
1219 }
1220
1221 // Can not stop a review whe not in review.
1222 $this->setUser($reviewer);
1223 $plan->set_status(plan::STATUS_DRAFT);
1224 try {
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());
1229 }
1230
1231 // Can not stop a review whe not in review.
1232 $this->setUser($reviewer);
1233 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1234 try {
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());
1239 }
1240
1241 // Can not stop a review whe not in review.
1242 $this->setUser($reviewer);
1243 $plan->set_status(plan::STATUS_ACTIVE);
1244 try {
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());
1249 }
1250
1251 // Can not stop a review whe not in review.
1252 $this->setUser($reviewer);
1253 $plan->set_status(plan::STATUS_COMPLETE);
1254 try {
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());
1259 }
1260
1261 // Stopping as the owner.
1262 $this->setUser($user);
1263 $plan->set_status(plan::STATUS_IN_REVIEW);
1264 try {
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);
1269 }
1270
1271 // Stopping review.
1272 $this->setUser($reviewer);
1273 api::plan_stop_review($plan);
1274 $plan->read();
1275 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1276
1277 // Stopping review by ID.
1278 $plan->set_status(plan::STATUS_IN_REVIEW);
1279 $plan->update();
1280 api::plan_stop_review($plan->get_id());
1281 $plan->read();
1282 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1283 }
1284
1285 /**
1286 * Testing approving the plan.
1287 */
1288 public function test_approve_plan() {
1289 $data = $this->setup_workflow_data();
96c2b847
FM
1290 $dg = $data['dg'];
1291 $lpg = $data['lpg'];
1292 $user = $data['user'];
1293 $reviewer = $data['reviewer'];
1294 $otheruser = $data['otheruser'];
1295 $plan = $data['plan'];
1296 $tplplan = $data['tplplan'];
3c230247
FM
1297
1298 // Set waiting for review.
1299 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1300 $tplplan->update();
1301 $plan->set_status(plan::STATUS_IN_REVIEW);
1302 $plan->update();
1303
1304 // Foreign user cannot do anything.
1305 $this->setUser($otheruser);
1306 try {
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);
1311 }
1312
1313 // Can not change a plan based on a template.
1314 $this->setUser($reviewer);
1315 try {
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());
1320 }
1321
1322 // Can not approve a plan already approved.
1323 $this->setUser($reviewer);
1324 $plan->set_status(plan::STATUS_ACTIVE);
1325 try {
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());
1330 }
1331
1332 // Can not approve a plan already approved.
1333 $this->setUser($reviewer);
1334 $plan->set_status(plan::STATUS_COMPLETE);
1335 try {
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());
1340 }
1341
1342 // Approve as the owner.
1343 $this->setUser($user);
1344 $plan->set_status(plan::STATUS_IN_REVIEW);
1345 try {
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);
1350 }
1351
1352 // Approve plan from in review.
1353 $this->setUser($reviewer);
1354 api::approve_plan($plan);
1355 $plan->read();
1356 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1357
1358 // Approve plan by ID.
1359 $plan->set_status(plan::STATUS_IN_REVIEW);
1360 $plan->update();
1361 api::approve_plan($plan->get_id());
1362 $plan->read();
1363 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1364
1365 // Approve plan from draft.
1366 $plan->set_status(plan::STATUS_DRAFT);
1367 $plan->update();
1368 api::approve_plan($plan);
1369 $plan->read();
1370 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1371
1372 // Approve plan from waiting for review.
1373 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1374 $plan->update();
1375 api::approve_plan($plan);
1376 $plan->read();
1377 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1378 }
1379
1380 /**
1381 * Testing stopping the review.
1382 */
1383 public function test_unapprove_plan() {
1384 $data = $this->setup_workflow_data();
96c2b847
FM
1385 $dg = $data['dg'];
1386 $lpg = $data['lpg'];
1387 $user = $data['user'];
1388 $reviewer = $data['reviewer'];
1389 $otheruser = $data['otheruser'];
1390 $plan = $data['plan'];
1391 $tplplan = $data['tplplan'];
3c230247
FM
1392
1393 // Set waiting for review.
1394 $tplplan->set_status(plan::STATUS_ACTIVE);
1395 $tplplan->update();
1396 $plan->set_status(plan::STATUS_ACTIVE);
1397 $plan->update();
1398
1399 // Foreign user cannot do anything.
1400 $this->setUser($otheruser);
1401 try {
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);
1406 }
1407
1408 // Can not change a plan based on a template.
1409 $this->setUser($reviewer);
1410 try {
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());
1415 }
1416
1417 // Can not unapprove a non-draft plan.
1418 $this->setUser($reviewer);
1419 $plan->set_status(plan::STATUS_DRAFT);
1420 try {
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());
1425 }
1426
1427 // Can not unapprove a non-draft plan.
1428 $this->setUser($reviewer);
1429 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1430 try {
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());
1435 }
1436
1437 // Can not unapprove a non-draft plan.
1438 $this->setUser($reviewer);
1439 $plan->set_status(plan::STATUS_IN_REVIEW);
1440 try {
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());
1445 }
1446
1447 // Can not unapprove a non-draft plan.
1448 $this->setUser($reviewer);
1449 $plan->set_status(plan::STATUS_COMPLETE);
1450 try {
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());
1455 }
1456
1457 // Unapprove as the owner.
1458 $this->setUser($user);
1459 $plan->set_status(plan::STATUS_ACTIVE);
1460 try {
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);
1465 }
1466
1467 // Unapprove plan.
1468 $this->setUser($reviewer);
1469 api::unapprove_plan($plan);
1470 $plan->read();
1471 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1472
1473 // Unapprove plan by ID.
1474 $plan->set_status(plan::STATUS_ACTIVE);
1475 $plan->update();
1476 api::unapprove_plan($plan->get_id());
1477 $plan->read();
1478 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1479 }
1480
192569ed
JPG
1481 /**
1482 * Test update plan and the managing of archived user competencies.
1483 */
1484 public function test_update_plan_manage_archived_competencies() {
1485 global $DB;
1486
1487 $this->resetAfterTest(true);
1488 $dg = $this->getDataGenerator();
922634d3 1489 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
192569ed
JPG
1490
1491 $syscontext = context_system::instance();
1492
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'
1498 ));
b90e2205
FM
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);
192569ed
JPG
1503 $dg->role_assign($manageownrole, $user->id, $syscontext->id);
1504 $this->setUser($user);
1505
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()));
1511
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));
1515
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()));
1520
1521 $uclist = array(
1522 $lpg->create_user_competency(array(
1523 'userid' => $user->id,
1524 'competencyid' => $c1->get_id(),
1525 'proficiency' => true,
1526 'grade' => 1
1527 )),
1528 $lpg->create_user_competency(array(
1529 'userid' => $user->id,
1530 'competencyid' => $c2->get_id(),
1531 'proficiency' => false,
1532 'grade' => 2
1533 ))
1534 );
1535
1536 // Change status of the plan to complete.
1537 $record = $plan->to_record();
67bc0eaf 1538 $record->status = \core_competency\plan::STATUS_COMPLETE;
192569ed 1539
5bfab685
FM
1540 try {
1541 $plan = api::update_plan($record);
1542 $this->fail('We cannot complete a plan using api::update_plan().');
1543 } catch (coding_exception $e) {
96c2b847 1544 // All good.
5bfab685
FM
1545 }
1546 api::complete_plan($plan);
192569ed
JPG
1547
1548 // Check that user compretencies are now in user_competency_plan objects and still in user_competency.
67bc0eaf
FM
1549 $this->assertEquals(2, \core_competency\user_competency::count_records());
1550 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
192569ed 1551
67bc0eaf 1552 $usercompetenciesplan = \core_competency\user_competency_plan::get_records();
192569ed
JPG
1553
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());
1559
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());
1565
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());
1571
192569ed
JPG
1572 // Change status of the plan to active.
1573 $record = $plan->to_record();
67bc0eaf 1574 $record->status = \core_competency\plan::STATUS_ACTIVE;
192569ed 1575
d805cc37
IT
1576 try {
1577 api::update_plan($record);
1578 $this->fail('Completed plan can not be edited');
1579 } catch (coding_exception $e) {
96c2b847 1580 // All good.
d805cc37 1581 }
192569ed 1582
d805cc37 1583 api::reopen_plan($record->id);
192569ed 1584 // Check that user_competency_plan objects are deleted if the plan status is changed to another status.
67bc0eaf
FM
1585 $this->assertEquals(2, \core_competency\user_competency::count_records());
1586 $this->assertEquals(0, \core_competency\user_competency_plan::count_records());
192569ed
JPG
1587 }
1588
af3fa58f
IT
1589 /**
1590 * Test completing plan does not change the order of competencies.
1591 */
1592 public function test_complete_plan_doesnot_change_order() {
1593 global $DB;
1594
1595 $this->resetAfterTest(true);
1596 $this->setAdminUser();
1597 $dg = $this->getDataGenerator();
922634d3 1598 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
af3fa58f
IT
1599
1600 $syscontext = context_system::instance();
1601
1602 // Create users and roles for the test.
1603 $user = $dg->create_user();
1604
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()));
1610
1611 // Create two plans and assign competencies.
1612 $plan = $lpg->create_plan(array('userid' => $user->id));
1613
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()));
1617
1618 // Changing competencies order in plan competency.
1619 api::reorder_plan_competency($plan->get_id(), $c1->get_id(), $c3->get_id());
1620
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());
1625
1626 // Completing plan.
1627 api::complete_plan($plan);
1628
1629 $competencies = api::list_plan_competencies($plan);
1630
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());
1635
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()));
1642
1643 $lpg->create_template_competency(array(
1644 'templateid' => $template->get_id(),
1645 'competencyid' => $c1->get_id()
1646 ));
1647 $lpg->create_template_competency(array(
1648 'templateid' => $template->get_id(),
1649 'competencyid' => $c2->get_id()
1650 ));
1651 $lpg->create_template_competency(array(
1652 'templateid' => $template->get_id(),
1653 'competencyid' => $c3->get_id()
1654 ));
1655 // Reorder competencies in template.
1656 api::reorder_template_competency($template->get_id(), $c1->get_id(), $c3->get_id());
1657
1658 // Create plan from template.
1659 $plan = api::create_plan_from_template($template->get_id(), $user->id);
1660
1661 $competencies = api::list_plan_competencies($plan);
1662
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());
1667
1668 // Completing plan.
1669 api::complete_plan($plan);
1670
1671 $competencies = api::list_plan_competencies($plan);
1672
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());
1677 }
1678
192569ed
JPG
1679 /**
1680 * Test remove plan and the managing of archived user competencies.
1681 */
1682 public function test_delete_plan_manage_archived_competencies() {
1683 $this->resetAfterTest(true);
1684 $dg = $this->getDataGenerator();
922634d3 1685 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
192569ed
JPG
1686
1687 $syscontext = context_system::instance();
1688
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'
1694 ));
b90e2205
FM
1695 assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $managerole, $syscontext->id);
1696 assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $managerole, $syscontext->id);
192569ed
JPG
1697 $dg->role_assign($managerole, $user->id, $syscontext->id);
1698 $this->setUser($user);
1699
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()));
1705
1706 // Create completed plan with records in user_competency.
67bc0eaf 1707 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
192569ed
JPG
1708
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()));
1711
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()));
1714
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()));
1719
1720 api::delete_plan($completedplan->get_id());
1721
1722 // Check that achived user competencies are deleted.
67bc0eaf
FM
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());
192569ed
JPG
1726 }
1727
1728 /**
1729 * Test listing of plan competencies.
1730 */
1731 public function test_list_plan_competencies_manage_archived_competencies() {
1732 $this->resetAfterTest(true);
1733 $dg = $this->getDataGenerator();
922634d3 1734 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
192569ed
JPG
1735
1736 $syscontext = context_system::instance();
1737
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'
1743 ));
b90e2205
FM
1744 assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $viewrole, $syscontext->id);
1745 assign_capability('moodle/competency:planview', CAP_ALLOW, $viewrole, $syscontext->id);
192569ed
JPG
1746 $dg->role_assign($viewrole, $user->id, $syscontext->id);
1747 $this->setUser($user);
1748
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()));
1754
1755 // Create draft plan with records in user_competency.
1756 $draftplan = $lpg->create_plan(array('userid' => $user->id));
1757
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()));
1761
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()));
1764
1765 // Check that user_competency objects are returned when plan status is not complete.
1766 $plancompetencies = api::list_plan_competencies($draftplan);
1767
1768 $this->assertCount(3, $plancompetencies);
67bc0eaf 1769 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[0]->usercompetency);
192569ed
JPG
1770 $this->assertEquals($uc1->get_id(), $plancompetencies[0]->usercompetency->get_id());
1771 $this->assertNull($plancompetencies[0]->usercompetencyplan);
1772
67bc0eaf 1773 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[1]->usercompetency);
192569ed
JPG
1774 $this->assertEquals($uc2->get_id(), $plancompetencies[1]->usercompetency->get_id());
1775 $this->assertNull($plancompetencies[1]->usercompetencyplan);
1776
67bc0eaf 1777 $this->assertInstanceOf('\core_competency\user_competency', $plancompetencies[2]->usercompetency);
192569ed
JPG
1778 $this->assertEquals(0, $plancompetencies[2]->usercompetency->get_id());
1779 $this->assertNull($plancompetencies[2]->usercompetencyplan);
1780
1781 // Create completed plan with records in user_competency_plan.
67bc0eaf 1782 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \core_competency\plan::STATUS_COMPLETE));
192569ed
JPG
1783
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()));
1787
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()));
192569ed
JPG
1792 $ucp3 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c3->get_id(),
1793 'planid' => $completedplan->get_id()));
1794
1795 // Check that user_competency_plan objects are returned when plan status is complete.
1796 $plancompetencies = api::list_plan_competencies($completedplan);
1797
1798 $this->assertCount(3, $plancompetencies);
67bc0eaf 1799 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[0]->usercompetencyplan);
192569ed
JPG
1800 $this->assertEquals($ucp1->get_id(), $plancompetencies[0]->usercompetencyplan->get_id());
1801 $this->assertNull($plancompetencies[0]->usercompetency);
67bc0eaf 1802 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[1]->usercompetencyplan);
192569ed
JPG
1803 $this->assertEquals($ucp2->get_id(), $plancompetencies[1]->usercompetencyplan->get_id());
1804 $this->assertNull($plancompetencies[1]->usercompetency);
67bc0eaf 1805 $this->assertInstanceOf('\core_competency\user_competency_plan', $plancompetencies[2]->usercompetencyplan);
192569ed
JPG
1806 $this->assertEquals($ucp3->get_id(), $plancompetencies[2]->usercompetencyplan->get_id());
1807 $this->assertNull($plancompetencies[2]->usercompetency);
1808 }
1809
bee480a4
FM
1810 public function test_create_template_cohort() {
1811 $this->resetAfterTest(true);
1812 $this->setAdminUser();
1813
1814 $dg = $this->getDataGenerator();
922634d3 1815 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
bee480a4
FM
1816
1817 $c1 = $dg->create_cohort();
1818 $c2 = $dg->create_cohort();
1819 $t1 = $lpg->create_template();
1820 $t2 = $lpg->create_template();
1821
67bc0eaf 1822 $this->assertEquals(0, \core_competency\template_cohort::count_records());
bee480a4
FM
1823
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);
1827
67bc0eaf
FM
1828 $this->assertEquals(2, \core_competency\template_cohort::count_records());
1829 $this->assertInstanceOf('core_competency\template_cohort', $result);
bee480a4
FM
1830 $this->assertEquals($c2->id, $result->get_cohortid());
1831 $this->assertEquals($t1->get_id(), $result->get_templateid());
67bc0eaf
FM
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())));
bee480a4
FM
1834 }
1835
6f0c979f
FM
1836 public function test_create_template_cohort_permissions() {
1837 $this->resetAfterTest(true);
1838
1839 $dg = $this->getDataGenerator();
922634d3 1840 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
6f0c979f
FM
1841 $cat = $dg->create_category();
1842 $catcontext = context_coursecat::instance($cat->id);
1843 $syscontext = context_system::instance();
1844
1845 $user = $dg->create_user();
1846 $role = $dg->create_role();
b90e2205 1847 assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $role, $syscontext->id, true);
6f0c979f
FM
1848 $dg->role_assign($role, $user->id, $syscontext->id);
1849
1850 $cohortrole = $dg->create_role();
1851 assign_capability('moodle/cohort:view', CAP_ALLOW, $cohortrole, $syscontext->id, true);
1852
1853 accesslib_clear_all_caches_for_unit_testing();
1854
1855 $c1 = $dg->create_cohort();
1856 $c2 = $dg->create_cohort(array('visible' => 0, 'contextid' => $catcontext->id));
1857 $t1 = $lpg->create_template();
1858
67bc0eaf 1859 $this->assertEquals(0, \core_competency\template_cohort::count_records());
6f0c979f
FM
1860
1861 $this->setUser($user);
1862 $result = api::create_template_cohort($t1, $c1);
67bc0eaf 1863 $this->assertInstanceOf('core_competency\\template_cohort', $result);
6f0c979f
FM
1864
1865 try {
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.
1870 }
1871
1872 // Try again with the right permissions.
1873 $dg->role_assign($cohortrole, $user->id, $catcontext->id);
1874 accesslib_clear_all_caches_for_unit_testing();
1875
1876 $result = api::create_template_cohort($t1, $c2);
67bc0eaf 1877 $this->assertInstanceOf('core_competency\\template_cohort', $result);
6f0c979f
FM
1878 }
1879
5a4ee001
IT
1880 public function test_delete_template() {
1881 $this->resetAfterTest(true);
1882 $this->setAdminUser();
1883
1884 $dg = $this->getDataGenerator();
922634d3 1885 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
5a4ee001
IT
1886
1887 $c1 = $dg->create_cohort();
1888 $c2 = $dg->create_cohort();
1889 $template = $lpg->create_template();
1890 $id = $template->get_id();
1891
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));
1895
1896 // Check pre-test.
67bc0eaf
FM
1897 $this->assertTrue(\core_competency\template::record_exists($id));
1898 $this->assertEquals(2, \core_competency\template_cohort::count_records(array('templateid' => $id)));
5a4ee001
IT
1899
1900 $result = api::delete_template($template->get_id());
1901 $this->assertTrue($result);
1902
1903 // Check that the template deos not exist anymore.
67bc0eaf 1904 $this->assertFalse(\core_competency\template::record_exists($id));
5a4ee001
IT
1905
1906 // Test if associated cohorts are also deleted.
67bc0eaf 1907 $this->assertEquals(0, \core_competency\template_cohort::count_records(array('templateid' => $id)));
5a4ee001
IT
1908 }
1909
bee480a4
FM
1910 public function test_delete_template_cohort() {
1911 $this->resetAfterTest(true);
1912 $this->setAdminUser();
1913
1914 $dg = $this->getDataGenerator();
922634d3 1915 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
bee480a4
FM
1916
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));
1923
67bc0eaf
FM
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())));
bee480a4
FM
1927
1928 // Delete existing.
1929 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1930 $this->assertTrue($result);
67bc0eaf
FM
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())));
bee480a4
FM
1934
1935 // Delete non-existant.
1936 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1937 $this->assertTrue($result);
67bc0eaf
FM
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())));
bee480a4 1941 }
4c0e8167 1942
914b580e
FM
1943 public function test_add_evidence_log() {
1944 $this->resetAfterTest(true);
1945 $dg = $this->getDataGenerator();
922634d3 1946 $lpg = $dg->get_plugin_generator('core_competency');
914b580e
FM
1947
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()));
1953
1954 // Creating a standard evidence with minimal information.
67bc0eaf 1955 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata', 'error');
914b580e 1956 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 1963 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get_action());
914b580e
FM
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());
1970
1971 // Creating a standard evidence with more information.
67bc0eaf 1972 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata', 'error',
d17cbbfb 1973 '$a', false, 'http://moodle.org', null, 2, 'The evidence of prior learning were reviewed.');
914b580e 1974 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 1981 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $evidence->get_action());
914b580e
FM
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());
d17cbbfb 1988 $this->assertSame('The evidence of prior learning were reviewed.', $evidence->get_note());
914b580e
FM
1989
1990 // Creating a standard evidence and send for review.
67bc0eaf 1991 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
914b580e
FM
1992 'error', null, true);
1993 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
1996
1997 // Trying to pass a grade should fail.
1998 try {
67bc0eaf 1999 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
96c2b847 2000 'error', null, false, null, 1);
914b580e
FM
2001 $this->fail('A grade can not be set');
2002 } catch (coding_exception $e) {
2003 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2004 }
2005 }
2006
914b580e
FM
2007 public function test_add_evidence_complete() {
2008 $this->resetAfterTest(true);
2009 $dg = $this->getDataGenerator();
922634d3 2010 $lpg = $dg->get_plugin_generator('core_competency');
914b580e
FM
2011
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));
914b580e
FM
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));
914b580e
FM
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()));
2028
2029 // Creating an evidence with minimal information.
67bc0eaf 2030 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
914b580e
FM
2031 'error');
2032 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 2039 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
914b580e
FM
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());
2046
2047 // Creating an evidence complete on competency with custom scale.
67bc0eaf 2048 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
914b580e
FM
2049 'error');
2050 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 2057 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
914b580e
FM
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());
2064
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());
67bc0eaf 2070 $evidence = api::add_evidence($u1->id, $c3->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
914b580e
FM
2071 'error');
2072 $evidence->read();
2073 $uc->read();
67bc0eaf 2074 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc->get_status());
914b580e
FM
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());
67bc0eaf 2079 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $evidence->get_action());
914b580e
FM
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());
2086
2087 // Creating a standard evidence and send for review.
67bc0eaf 2088 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
914b580e
FM
2089 'error', null, true);
2090 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
2093
2094 // Trying to pass a grade should throw an exception.
2095 try {
67bc0eaf 2096 api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_COMPLETE, 'invaliddata',
914b580e
FM
2097 'error', null, false, null, 1);
2098 } catch (coding_exception $e) {
2099 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
2100 }
2101 }
2102
2103 public function test_add_evidence_override() {
2104 $this->resetAfterTest(true);
2105 $dg = $this->getDataGenerator();
922634d3 2106 $lpg = $dg->get_plugin_generator('core_competency');
914b580e
FM
2107
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()));
2112
2113 // Creating an evidence with minimal information.
67bc0eaf 2114 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
914b580e
FM
2115 'error');
2116 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 2123 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
914b580e
FM
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());
2130
2131 // Creating an evidence with a grade information.
67bc0eaf 2132 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
914b580e
FM
2133 'error', null, false, null, 3);
2134 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 2141 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
914b580e
FM
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());
2148
2149 // Creating an evidence with another grade information.
67bc0eaf 2150 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
914b580e
FM
2151 'error', null, false, null, 1);
2152 $evidence->read();
67bc0eaf
FM
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());
914b580e
FM
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());
67bc0eaf 2159 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
914b580e
FM
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());
2166
2167 // Creating reverting the grade and send for review.
67bc0eaf 2168 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_OVERRIDE, 'invaliddata',
914b580e
FM
2169 'error', null, true);
2170 $evidence->read();
67bc0eaf 2171 $uc = \core_competency\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
914b580e
FM
2172 $this->assertSame(null, $uc->get_grade());
2173 $this->assertSame(null, $uc->get_proficiency());
67bc0eaf 2174 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
914b580e
FM
2175 $this->assertSame(null, $evidence->get_grade());
2176 }
2177
2178 public function test_add_evidence_and_send_for_review() {
2179 $this->resetAfterTest(true);
2180 $dg = $this->getDataGenerator();
922634d3 2181 $lpg = $dg->get_plugin_generator('core_competency');
914b580e
FM
2182
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()));
2187
2188 // Non-existing user competencies are created up for review.
67bc0eaf 2189 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
914b580e 2190 'error', null, true);
67bc0eaf
FM
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());
914b580e
FM
2193
2194 // Existing user competencies sent for review don't change.
67bc0eaf 2195 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
914b580e
FM
2196 'error', null, true);
2197 $uc->read();
67bc0eaf 2198 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
914b580e
FM
2199
2200 // A user competency with a status non-idle won't change.
67bc0eaf 2201 $uc->set_status(\core_competency\user_competency::STATUS_IN_REVIEW);
914b580e 2202 $uc->update();
67bc0eaf 2203 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \core_competency\evidence::ACTION_LOG, 'invaliddata',
914b580e
FM
2204 'error', null, true);
2205 $uc->read();
67bc0eaf 2206 $this->assertEquals(\core_competency\user_competency::STATUS_IN_REVIEW, $uc->get_status());
914b580e
FM
2207 }
2208
4c0e8167
SG
2209 /**
2210 * Test add evidence for existing user_competency.
2211 */
2212 public function test_add_evidence_existing_user_competency() {
2213 $this->resetAfterTest(true);
2214 $dg = $this->getDataGenerator();
922634d3 2215 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
4c0e8167
SG
2216
2217 $syscontext = context_system::instance();
2218
2219 // Create users.
2220 $user = $dg->create_user();
2221 $this->setUser($user);
2222
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()));
914b580e
FM
2229 $this->assertSame(null, $uc->get_grade());
2230 $this->assertSame(null, $uc->get_proficiency());
4c0e8167
SG
2231
2232 // Create an evidence and check it was created with the right usercomptencyid and information.
67bc0eaf 2233 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
914b580e 2234 'invalidevidencedesc', 'tool_lp', array('a' => 'b'), false, 'http://moodle.org', 1, 2);
67bc0eaf 2235 $this->assertEquals(1, \core_competency\evidence::count_records());
4c0e8167
SG
2236
2237 $evidence->read();
914b580e 2238 $uc->read();
4c0e8167
SG
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());
914b580e 2243 $this->assertEquals('http://moodle.org', $evidence->get_url());
67bc0eaf 2244 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
914b580e 2245 $this->assertEquals(2, $evidence->get_actionuserid());
4c0e8167 2246 $this->assertEquals(1, $evidence->get_grade());
914b580e
FM
2247 $this->assertEquals(1, $uc->get_grade());
2248 $this->assertEquals(0, $uc->get_proficiency());
4c0e8167
SG
2249 }
2250
2251 /**
914b580e 2252 * Test add evidence for non-existing user_competency.
4c0e8167
SG
2253 */
2254 public function test_add_evidence_no_existing_user_competency() {
2255 $this->resetAfterTest(true);
2256 $dg = $this->getDataGenerator();
922634d3 2257 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
4c0e8167
SG
2258
2259 $syscontext = context_system::instance();
2260
2261 // Create users.
2262 $user = $dg->create_user();
2263 $this->setUser($user);
2264
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()));
67bc0eaf 2269 $this->assertEquals(0, \core_competency\user_competency::count_records());
4c0e8167 2270
914b580e 2271 // Create an evidence without a user competency record.
67bc0eaf 2272 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \core_competency\evidence::ACTION_OVERRIDE,
914b580e 2273 'invalidevidencedesc', 'tool_lp', 'Hello world!', false, 'http://moodle.org', 1, 2);
67bc0eaf
FM
2274 $this->assertEquals(1, \core_competency\evidence::count_records());
2275 $this->assertEquals(1, \core_competency\user_competency::count_records());
4c0e8167 2276
67bc0eaf 2277 $uc = \core_competency\user_competency::get_record(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
914b580e
FM
2278 $evidence->read();
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());
67bc0eaf 2284 $this->assertEquals(\core_competency\evidence::ACTION_OVERRIDE, $evidence->get_action());
914b580e
FM
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());
2289 }
2290
9373acf6
FM
2291 public function test_add_evidence_applies_competency_rules() {
2292 $this->resetAfterTest(true);
2293 $dg = $this->getDataGenerator();
922634d3 2294 $lpg = $dg->get_plugin_generator('core_competency');
9373acf6
FM
2295 $syscontext = context_system::instance();
2296 $ctxid = $syscontext->id;
2297
2298 $u1 = $dg->create_user();
2299
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()));
2312
2313 // Setting up the rules.
67bc0eaf
FM
2314 $c1->set_ruletype('core_competency\\competency_rule_all');
2315 $c1->set_ruleoutcome(\core_competency\competency::OUTCOME_COMPLETE);
9373acf6 2316 $c1->update();
67bc0eaf
FM
2317 $c2->set_ruletype('core_competency\\competency_rule_all');
2318 $c2->set_ruleoutcome(\core_competency\competency::OUTCOME_RECOMMEND);
9373acf6 2319 $c2->update();
67bc0eaf
FM
2320 $c3->set_ruletype('core_competency\\competency_rule_all');
2321 $c3->set_ruleoutcome(\core_competency\competency::OUTCOME_EVIDENCE);
9373acf6 2322 $c3->update();
67bc0eaf
FM
2323 $c4->set_ruletype('core_competency\\competency_rule_all');
2324 $c4->set_ruleoutcome(\core_competency\competency::OUTCOME_NONE);
9373acf6
FM
2325 $c4->update();
2326
2327 // Confirm the current data.
2328 $this->assertEquals(0, user_competency::count_records());
2329 $this->assertEquals(0, evidence::count_records());
2330
2331 // Let's do this!
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())));
2337
9373acf6
FM
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())));
2347
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())));
2356
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())));
2365
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())));
2374
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())));
2380
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');
2383 }
2384
41460929
JP
2385 /**
2386 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2387 * grading a user competency in the system context.
2388 */
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();
2393
2394 // Create a student.
2395 $student = $dg->create_user();
2396
2397 // Create a competency for the course.
922634d3 2398 $lpg = $dg->get_plugin_generator('core_competency');
41460929
JP
2399 $framework = $lpg->create_framework();
2400 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2401
2402 // Add evidence.
2403 api::add_evidence($student->id, $comp, $syscontext, evidence::ACTION_OVERRIDE,
2404 'commentincontext', 'core', null, false, null, 1);
2405
2406 // Query for user_competency_course data.
2407 $filterparams = array(
2408 'userid' => $student->id,
2409 'competencyid' => $comp->get_id(),
2410 );
67bc0eaf 2411 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
41460929
JP
2412 // There should be no user_competency_course object created when grading.
2413 $this->assertFalse($usercompcourse);
2414 }
2415
41460929
JP
2416 /**
2417 * Tests for the user_competency_course data when api::add_evidence() is invoked when
2418 * grading a user competency in a course.
2419 */
2420 public function test_add_evidence_user_competency_course_grade_in_course() {
2421 global $USER;
2422
2423 $this->resetAfterTest(true);
2424 $dg = $this->getDataGenerator();
2425
2426 // Create a course.
2427 $course = $dg->create_course();
fdd85ede
DW
2428 $record = array('courseid' => $course->id, 'pushratingstouserplans' => false);
2429 $settings = new course_competency_settings(0, (object) $record);
2430 $settings->create();
41460929
JP
2431 $coursecontext = context_course::instance($course->id);
2432
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);
2439
2440 // Create a competency for the course.
922634d3 2441 $lpg = $dg->get_plugin_generator('core_competency');
41460929 2442 $framework = $lpg->create_framework();
fdd85ede 2443 // Do not push ratings from course to user plans.
41460929
JP
2444 $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2445 $lpg->create_course_competency(array('courseid' => $course->id, 'competencyid' => $comp->get_id()));
2446
41460929
JP
2447 // Query for user_competency_course data.
2448 $filterparams = array(
2449 'userid' => $student->id,
2450 'competencyid' => $comp->get_id(),
2451 'courseid' => $course->id
2452 );
41460929 2453
fdd85ede
DW
2454 // Add evidence that sets a grade to the course.
2455 $evidence = api::add_evidence($student->id, $comp, $coursecontext, evidence::ACTION_OVERRIDE,
41460929
JP
2456 'commentincontext', 'core', null, false, null, 3, $USER->id);
2457 // Get user competency course record.
67bc0eaf 2458 $usercompcourse = \core_competency\user_competency_course::get_record($filterparams);
fdd85ede 2459 // There should be a user_competency_course object when adding a grade.
41460929
JP
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());
2466
fdd85ede 2467 // Confirm that the user competency's grade/proficiency has not been affected by the grade.
41460929
JP
2468 $usercompetencyparams = [
2469 'userid' => $student->id,
2470 'competencyid' => $comp->get_id(),
2471 ];
67bc0eaf 2472 $usercompetency = \core_competency\user_competency::get_record($usercompetencyparams);
41460929
JP
2473 $this->assertNotEmpty($usercompetency);
2474 $this->assertNotEquals($usercompcourse->get_grade(), $usercompetency->get_grade());
2475 $this->assertNotEquals($usercompcourse->get_proficiency(), $usercompetency->get_proficiency());
2476 }
2477
914b580e
FM
2478 public function test_observe_course_completed() {
2479 $this->resetAfterTest(true);
2480 $dg = $this->getDataGenerator();
922634d3 2481 $lpg = $dg->get_plugin_generator('core_competency');
914b580e
FM
2482
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,
67bc0eaf 2493 'ruleoutcome' => \core_competency\course_competency::OUTCOME_NONE));
914b580e 2494 $cc2 = $lpg->create_course_competency(array('competencyid' => $c2->get_id(), 'courseid' => $course->id,
67bc0eaf 2495 'ruleoutcome' => \core_competency\course_competency::OUTCOME_EVIDENCE));
914b580e 2496 $cc3 = $lpg->create_course_competency(array('competencyid' => $c3->get_id(), 'courseid' => $course->id,
67bc0eaf 2497 'ruleoutcome' => \core_competency\course_competency::OUTCOME_RECOMMEND));
914b580e 2498 $cc4 = $lpg->create_course_competency(array('competencyid' => $c4->get_id(), 'courseid' => $course->id,
67bc0eaf 2499 'ruleoutcome' => \core_competency\course_competency::OUTCOME_COMPLETE));
914b580e
FM
2500
2501 $event = \core\event\course_completed::create(array(
2502 'objectid' => 1,
2503 'relateduserid' => $u1->id,
2504 'context' => $coursectx,
2505 'courseid' => $course->id,
2506 'other' => array('relateduserid' => $u1->id)
2507 ));
67bc0eaf
FM
2508 $this->assertEquals(0, \core_competency\user_competency::count_records());
2509 $this->assertEquals(0, \core_competency\evidence::count_records());
914b580e
FM
2510
2511 // Let's go!
2512 api::observe_course_completed($event);
67bc0eaf
FM
2513 $this->assertEquals(3, \core_competency\user_competency::count_records());
2514 $this->assertEquals(3, \core_competency\evidence::count_records());
914b580e
FM
2515
2516 // Outcome NONE did nothing.
67bc0eaf 2517 $this->assertFalse(\core_competency\user_competency::record_exists_select('userid = :uid AND competencyid = :cid', array(
914b580e
FM
2518 'uid' => $u1->id, 'cid' => $c1->get_id()
2519 )));
2520
2521 // Outcome evidence.
67bc0eaf
FM
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()));
914b580e
FM
2524
2525 $this->assertEquals(null, $uc2->get_grade());
2526 $this->assertEquals(null, $uc2->get_proficiency());
67bc0eaf 2527 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc2->get_status());
914b580e
FM
2528
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());
67bc0eaf 2535 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev2->get_action());
914b580e
FM
2536 $this->assertEquals(null, $ev2->get_actionuserid());
2537
2538 // Outcome recommend.
67bc0eaf
FM
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()));
914b580e
FM
2541
2542 $this->assertEquals(null, $uc3->get_grade());
2543 $this->assertEquals(null, $uc3->get_proficiency());
67bc0eaf 2544 $this->assertEquals(\core_competency\user_competency::STATUS_WAITING_FOR_REVIEW, $uc3->get_status());
914b580e
FM
2545
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());
67bc0eaf 2552 $this->assertEquals(\core_competency\evidence::ACTION_LOG, $ev3->get_action());
914b580e
FM
2553 $this->assertEquals(null, $ev3->get_actionuserid());
2554
2555 // Outcome complete.
67bc0eaf
FM
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()));
914b580e
FM
2558
2559 $this->assertEquals(3, $uc4->get_grade());
2560 $this->assertEquals(1, $uc4->get_proficiency());
67bc0eaf 2561 $this->assertEquals(\core_competency\user_competency::STATUS_IDLE, $uc4->get_status());
914b580e
FM
2562
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());
67bc0eaf 2569 $this->assertEquals(\core_competency\evidence::ACTION_COMPLETE, $ev4->get_action());
914b580e 2570 $this->assertEquals(null, $ev4->get_actionuserid());
4c0e8167 2571 }
d4c0a2f6 2572
db650737
DW
2573 public function test_list_course_modules_using_competency() {
2574 global $SITE;
2575
2576 $this->resetAfterTest(true);
2577 $dg = $this->getDataGenerator();
922634d3 2578 $lpg = $dg->get_plugin_generator('core_competency');
db650737
DW
2579 $u1 = $dg->create_user();
2580 $u2 = $dg->create_user();
2581 $course = $dg->create_course();
2582 $course2 = $dg->create_course();
2583
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());
2590
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);
2595
2596 $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
96c2b847 2597 $page = $pagegenerator->create_instance(array('course' => $course->id));
db650737
DW
2598
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());
f446b2e1 2602 $expected = array($cm->id);
db650737
DW
2603 $result = api::list_course_modules_using_competency($c->get_id(), $course->id);
2604 $this->assertEquals($expected, $result);
2605
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);
2610
2611 // Remove the link and check again.
2612 $result = api::remove_competency_from_course_module($cm, $c->get_id());
2613 $expected = true;
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);
2618
2619 // Now add 2 links.
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());
2625
2626 // Now re-order.
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());
2631
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());
2637 }
2638
d4c0a2f6
SG
2639 /**
2640 * Test update ruleoutcome for course_competency.
2641 */
d660824b 2642 public function test_set_ruleoutcome_course_competency() {
d4c0a2f6
SG
2643 $this->resetAfterTest(true);
2644 $dg = $this->getDataGenerator();
922634d3 2645 $lpg = $dg->get_plugin_generator('core_competency');
d4c0a2f6
SG
2646 $u1 = $dg->create_user();
2647 $u2 = $dg->create_user();
d660824b 2648 $course = $dg->create_course();
d4c0a2f6
SG
2649
2650 $this->setAdminUser();
2651 $f = $lpg->create_framework();
2652 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
d660824b 2653 $cc = api::add_competency_to_course($course->id, $c->get_id());
d4c0a2f6
SG
2654
2655 // Check record was created with default rule value Evidence.
67bc0eaf 2656 $this->assertEquals(1, \core_competency\course_competency::count_records());
d660824b 2657 $recordscc = api::list_course_competencies($course->id);
67bc0eaf 2658 $this->assertEquals(\core_competency\course_competency::OUTCOME_EVIDENCE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
d4c0a2f6
SG
2659
2660 // Check ruleoutcome value is updated to None.
d660824b 2661 $this->assertTrue(api::set_course_competency_ruleoutcome($recordscc[0]['coursecompetency']->get_id(),
67bc0eaf 2662 \core_competency\course_competency::OUTCOME_NONE));
d660824b 2663 $recordscc = api::list_course_competencies($course->id);
67bc0eaf 2664 $this->assertEquals(\core_competency\course_competency::OUTCOME_NONE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
d4c0a2f6
SG
2665 }
2666
4de456cd
SG
2667 /**
2668 * Test validation on grade on user_competency.
2669 */
2670 public function test_validate_grade_in_user_competency() {
2671 global $DB;
2672
2673 $this->resetAfterTest(true);
2674 $this->setAdminUser();
2675 $dg = $this->getDataGenerator();
922634d3 2676 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
4de456cd
SG
2677 $user = $dg->create_user();
2678
2679 $dg->create_scale(array("id" => "1", "scale" => "value1, value2"));
2680 $dg->create_scale(array("id" => "2", "scale" => "value3, value4, value5, value6"));
2681
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},'
10bf349e 2685 . '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
4de456cd
SG
2686
2687 // Create a framework with scale configuration1.
2688 $frm = array(
2689 'scaleid' => 1,
2690 'scaleconfiguration' => $scaleconfiguration1
2691 );
2692 $framework = $lpg->create_framework($frm);
2693 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2694
2695 // Create competency with its own scale configuration.
2696 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
2697 'scaleid' => 2,
2698 'scaleconfiguration' => $scaleconfiguration2
2699 ));
2700
2701 // Detecte invalid grade in competency using its framework competency scale.
2702 try {
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');
67bc0eaf 2707 } catch (\core_competency\invalid_persistent_exception $e) {
4de456cd
SG
2708 $this->assertTrue(true);
2709 }
2710
2711 // Detecte invalid grade in competency using its own scale.
2712 try {
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');
67bc0eaf 2717 } catch (\core_competency\invalid_persistent_exception $e) {
4de456cd
SG
2718 $this->assertTrue(true);
2719 }
2720
2721 // Accept valid grade in competency using its framework competency scale.
2722 try {
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);
67bc0eaf 2727 } catch (\core_competency\invalid_persistent_exception $e) {
4de456cd
SG
2728 $this->fail('Valide grade rejected in framework scale');
2729 }
2730
2731 // Accept valid grade in competency using its framework competency scale.
2732 try {
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);
67bc0eaf 2737 } catch (\core_competency\invalid_persistent_exception $e) {
4de456cd
SG
2738 $this->fail('Valide grade rejected in competency scale');
2739 }
2740 }
2741
964afa98
IT
2742 /**
2743 * Test when adding competency that belong to hidden framework to plan/template/course.
2744 */
2745 public function test_hidden_framework() {
2746 $this->resetAfterTest(true);
2747 $this->setAdminUser();
2748 $dg = $this->getDataGenerator();
922634d3 2749 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
964afa98
IT
2750 $user = $dg->create_user();
2751
2752 // Create a course.
2753 $cat1 = $dg->create_category();
2754 $course = $dg->create_course(array('category' => $cat1->id));
2755 // Create a template.
2756 $template = $lpg->create_template();
2757 // Create a plan.
2758 $plan = $lpg->create_plan(array('userid' => $user->id));
2759
2760 // Create a hidden framework.
2761 $frm = array(
2762 'visible' => false
2763 );
2764 $framework = $lpg->create_framework($frm);
2765 $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2766
2767 // Linking competency that belong to hidden framework to course.
2768 try {
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);
2773 }
2774
2775 // Adding competency that belong to hidden framework to template.
2776 try {
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);
2781 }
2782
2783 // Adding competency that belong to hidden framework to plan.
2784 try {
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);
2789 }
2790 }
2791
2792 /**
2793 * Test when using hidden template in plan/cohort.
2794 */
2795 public function test_hidden_template() {
2796 $this->resetAfterTest(true);
2797 $this->setAdminUser();
2798 $dg = $this->getDataGenerator();
922634d3 2799 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
964afa98
IT
2800 $user = $dg->create_user();
2801
2802 // Create a cohort.
2803 $cohort = $dg->create_cohort();
2804 // Create a hidden template.
2805 $template = $lpg->create_template(array('visible' => false));
2806
2807 // Can not link hidden template to plan.
2808 try {
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);
2813 }
2814
2815 // Can associate hidden template to cohort.
2816 $templatecohort = api::create_template_cohort($template->get_id(), $cohort->id);
67bc0eaf 2817 $this->assertInstanceOf('\core_competency\template_cohort', $templatecohort);
964afa98
IT
2818 }
2819
d3275795
SG
2820 /**
2821 * Test that completed plan created form a template does not change when template is modified.
2822 */
2823 public function test_completed_plan_doesnot_change() {
2824 global $DB;
2825
2826 $this->resetAfterTest(true);
2827 $this->setAdminUser();
2828 $dg = $this->getDataGenerator();
922634d3 2829 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
d3275795
SG
2830 $user = $dg->create_user();
2831
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()));
2838
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()));
2844
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);
2848
2849 // Check user competency plan created correctly.
67bc0eaf
FM
2850 $this->assertEquals(3, \core_competency\user_competency_plan::count_records());
2851 $ucp = \core_competency\user_competency_plan::get_records();
d3275795
SG
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());
2855
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());
2859
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());
2864 $ucp2 = array();
2865 foreach ($competencies as $id => $cmp) {
2866 $ucp2[] = $id;
2867 }
2868 $this->assertEquals(0, count(array_diff($ucp1, $ucp2)));
2869 }
20c2fe3e
FM
2870
2871 protected function setup_framework_for_reset_rules_tests() {
2872 $this->resetAfterTest(true);
2873 $dg = $this->getDataGenerator();
922634d3 2874 $lpg = $dg->get_plugin_generator('core_competency');
20c2fe3e
FM
2875
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()));
2887
2888 $c1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 2889 $c1->set_ruletype('core_competency\\competency_rule_all');
20c2fe3e
FM
2890 $c1->update();
2891 $c1a->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 2892 $c1a->set_ruletype('core_competency\\competency_rule_all');
20c2fe3e
FM
2893 $c1a->update();
2894 $c1a1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 2895 $c1a1->set_ruletype('core_competency\\competency_rule_all');
20c2fe3e
FM
2896 $c1a1->update();
2897 $c1b->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 2898 $c1b->set_ruletype('core_competency\\competency_rule_all');
20c2fe3e
FM
2899 $c1b->update();
2900 $c2->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 2901 $c2->set_ruletype('core_competency\\competency_rule_all');
20c2fe3e
FM
2902 $c2->update();
2903
2904 return array(
2905 'f1' => $f1,
2906 'c1' => $c1,
2907 'c1a' => $c1a,
2908 'c1a1' => $c1a1,
2909 'c1a1a' => $c1a1a,
2910 'c1b' => $c1b,
2911 'c1b1' => $c1b1,
2912 'c1b1a' => $c1b1a,
2913 'c2' => $c2,
2914 'c2a' => $c2a,
2915 );
2916 }
2917
2918 public function test_moving_competency_reset_rules_updown() {
96c2b847
FM
2919 $data = $this->setup_framework_for_reset_rules_tests();
2920 $f1 = $data['f1'];
2921 $c1 = $data['c1'];
2922 $c1a = $data['c1a'];
2923 $c1a1 = $data['c1a1'];
2924 $c1a1a = $data['c1a1a'];
2925 $c1b = $data['c1b'];
2926 $c1b1 = $data['c1b1'];
2927 $c1b1a = $data['c1b1a'];
2928 $c2 = $data['c2'];
2929 $c2a = $data['c2a'];
20c2fe3e
FM
2930
2931 // Moving up and down doesn't change anything.
2932 api::move_down_competency($c1a->get_id());
2933 $c1->read();
2934 $c1a->read();
2935 $c1a1->read();
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());
2940 $c1->read();
2941 $c1a->read();
2942 $c1a1->read();
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());
2946 }
2947
2948 public function test_moving_competency_reset_rules_parent() {
96c2b847
FM
2949 $data = $this->setup_framework_for_reset_rules_tests();
2950 $f1 = $data['f1'];
2951 $c1 = $data['c1'];
2952 $c1a = $data['c1a'];
2953 $c1a1 = $data['c1a1'];
2954 $c1a1a = $data['c1a1a'];
2955 $c1b = $data['c1b'];
2956 $c1b1 = $data['c1b1'];
2957 $c1b1a = $data['c1b1a'];
2958 $c2 = $data['c2'];
2959 $c2a = $data['c2a'];
20c2fe3e
FM
2960
2961 // Moving out of parent will reset the parent, and the destination.
2962 api::set_parent_competency($c1a->get_id(), $c1b->get_id());
2963 $c1->read();
2964 $c1a->read();
2965 $c1a1->read();
2966 $c1b->read();
2967 $c2->read();
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());
2973 }
2974
2975 public function test_moving_competency_reset_rules_totoplevel() {
96c2b847
FM
2976 $data = $this->setup_framework_for_reset_rules_tests();
2977 $f1 = $data['f1'];
2978 $c1 = $data['c1'];
2979 $c1a = $data['c1a'];
2980 $c1a1 = $data['c1a1'];
2981 $c1a1a = $data['c1a1a'];
2982 $c1b = $data['c1b'];
2983 $c1b1 = $data['c1b1'];
2984 $c1b1a = $data['c1b1a'];
2985 $c2 = $data['c2'];
2986 $c2a = $data['c2a'];
20c2fe3e
FM
2987
2988 // Moving to top level only affects the initial parent.
2989 api::set_parent_competency($c1a1->get_id(), 0);
2990 $c1->read();
2991 $c1a->read();
2992 $c1a1->read();
2993 $c1b->read();
2994 $c2->read();
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());
3000 }
3001
3002 public function test_moving_competency_reset_rules_fromtoplevel() {
96c2b847
FM
3003 $data = $this->setup_framework_for_reset_rules_tests();
3004 $f1 = $data['f1'];
3005 $c1 = $data['c1'];
3006 $c1a = $data['c1a'];
3007 $c1a1 = $data['c1a1'];
3008 $c1a1a = $data['c1a1a'];
3009 $c1b = $data['c1b'];
3010 $c1b1 = $data['c1b1'];
3011 $c1b1a = $data['c1b1a'];
3012 $c2 = $data['c2'];
3013 $c2a = $data['c2a'];
20c2fe3e
FM
3014
3015 // Moving from top level only affects the destination parent.
3016 api::set_parent_competency($c2->get_id(), $c1a1->get_id());
3017 $c1->read();
3018 $c1a->read();
3019 $c1a1->read();
3020 $c1b->read();
3021 $c2->read();
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());
3027 }
3028
3029 public function test_moving_competency_reset_rules_child() {
96c2b847
FM
3030 $data = $this->setup_framework_for_reset_rules_tests();
3031 $f1 = $data['f1'];
3032 $c1 = $data['c1'];
3033 $c1a = $data['c1a'];
3034 $c1a1 = $data['c1a1'];
3035 $c1a1a = $data['c1a1a'];
3036 $c1b = $data['c1b'];
3037 $c1b1 = $data['c1b1'];
3038 $c1b1a = $data['c1b1a'];
3039 $c2 = $data['c2'];
3040 $c2a = $data['c2a'];
20c2fe3e
FM
3041
3042 // Moving to a child of self resets self, parent and destination.
3043 api::set_parent_competency($c1a->get_id(), $c1a1->get_id());
3044 $c1->read();
3045 $c1a->read();
3046 $c1a1->read();
3047 $c1b->read();
3048 $c2->read();
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());
3054 }
3055
3056 public function test_create_competency_reset_rules() {
96c2b847
FM
3057 $data = $this->setup_framework_for_reset_rules_tests();
3058 $f1 = $data['f1'];
3059 $c1 = $data['c1'];
3060 $c1a = $data['c1a'];
3061 $c1a1 = $data['c1a1'];
3062 $c1a1a = $data['c1a1a'];
3063 $c1b = $data['c1b'];
3064 $c1b1 = $data['c1b1'];
3065 $c1b1a = $data['c1b1a'];
3066 $c2 = $data['c2'];
3067 $c2a = $data['c2a'];
20c2fe3e
FM
3068
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()));
3072 $c1->read();
3073 $c1a->read();
3074 $c1a1->read();
3075 $c1b->read();
3076 $c2->read();
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());
3082 }
3083
3084 public function test_delete_competency_reset_rules() {
96c2b847
FM
3085 $data = $this->setup_framework_for_reset_rules_tests();
3086 $f1 = $data['f1'];
3087 $c1 = $data['c1'];
3088 $c1a = $data['c1a'];
3089 $c1a1 = $data['c1a1'];
3090 $c1a1a = $data['c1a1a'];
3091 $c1b = $data['c1b'];
3092 $c1b1 = $data['c1b1'];
3093 $c1b1a = $data['c1b1a'];
3094 $c2 = $data['c2'];
3095 $c2a = $data['c2a'];
20c2fe3e
FM
3096
3097 // Deleting a competency resets the rule of its parent.
3098 api::delete_competency($c1a->get_id());
3099 $c1->read();
3100 $c1b->read();
3101 $c2->read();
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());
3105 }
8fabc738
SG
3106
3107 public function test_template_has_related_data() {
3108 $this->resetAfterTest(true);
3109 $this->setAdminUser();
3110
3111 $dg = $this->getDataGenerator();
3112 $user = $dg->create_user();
922634d3 3113 $lpg = $dg->get_plugin_generator('core_competency');
8fabc738
SG
3114 $tpl1 = $lpg->create_template();
3115 $tpl2 = $lpg->create_template();
3116
3117 // Create plans for first template.
3118 $time = time();
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));
3121
3122 $this->assertTrue(api::template_has_related_data($tpl1->get_id()));
3123 $this->assertFalse(api::template_has_related_data($tpl2->get_id()));
3124
3125 }
3126
3127 public function test_delete_template_delete_plans() {
3128 $this->resetAfterTest(true);
3129 $this->setAdminUser();
3130
3131 $dg = $this->getDataGenerator();
922634d3 3132 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
8fabc738
SG
3133
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()));
3138
3139 $tpl = $lpg->create_template();
3140
3141 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id(),
3142 'sortorder' => 1));
3143 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2->get_id(),
3144 'sortorder' => 2));
3145
3146 $p1 = $lpg->create_plan(array('templateid' => $tpl->get_id(), 'userid' => $u1->id));
3147
3148 // Check pre-test.
67bc0eaf
FM
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()))));
8fabc738
SG
3152
3153 $result = api::delete_template($tpl->get_id(), true);
3154 $this->assertTrue($result);
3155
3156 // Check that the template does not exist anymore.
67bc0eaf 3157 $this->assertFalse(\core_competency\template::record_exists($tpl->get_id()));
8fabc738
SG
3158
3159 // Check that associated competencies are also deleted.
67bc0eaf 3160 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get_id()));
8fabc738
SG
3161
3162 // Check that associated plan are also deleted.
67bc0eaf 3163 $this->assertEquals(0, count(\core_competency\plan::get_records(array('templateid' => $tpl->get_id()))));
8fabc738
SG
3164 }
3165
3166 public function test_delete_template_unlink_plans() {
3167 $this->resetAfterTest(true);
3168 $this->setAdminUser();
3169
3170 $dg = $this->getDataGenerator();
922634d3 3171 $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
8fabc738
SG
3172
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()));
3177
3178 $tpl = $lpg->create_template();
3179
3180 $tplc1 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c1->get_id(),
3181 'sortorder' => 1));
3182 $tplc2 = $lpg->create_template_competency(array('templateid' => $tpl->get_id(), 'competencyid' => $c2->get_id(),
3183 'sortorder' => 2));
3184
3185 $p1 = $lpg->create_plan(array('templateid' => $tpl->get_id(), 'userid' => $u1->id));
3186
3187 // Check pre-test.
67bc0eaf
FM
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()))));
8fabc738
SG
3191
3192 $result = api::delete_template($tpl->get_id(), false);
3193 $this->assertTrue($result);
3194
3195 // Check that the template does not exist anymore.
67bc0eaf 3196 $this->assertFalse(\core_competency\template::record_exists($tpl->get_id()));
8fabc738
SG
3197
3198 // Check that associated competencies are also deleted.
67bc0eaf 3199 $this->assertEquals(0, \core_competency\template_competency::count_competencies($tpl->get_id()));
8fabc738
SG
3200
3201 // Check that associated plan still exist but unlink from template.
67bc0eaf 3202 $plans = \core_competency\plan::get_records(array('id' => $p1->get_id()));
8fabc738
SG
3203 $this->assertEquals(1, count($plans));
3204 $this->assertEquals($plans[0]->get_origtemplateid(), $tpl->get_id());
3205 $this->assertNull($plans[0]->get_templateid());
3206 }
9a325eda
IT
3207
3208 public function test_delete_competency() {
3209 $this->resetAfterTest(true);
3210 $dg = $this->getDataGenerator();
922634d3 3211 $lpg = $dg->get_plugin_generator('core_competency');
9a325eda
IT
3212 $this->setAdminUser();
3213
3214 $u1 = $dg->create_user();
3215
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()));
3223
3224 // Set rules on parent competency.
3225 $c1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
67bc0eaf 3226 $c1->set_ruletype('core_competency\\competency_rule_all');
9a325eda
IT
3227 $c1->update();
3228
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()
3234 ));
3235 $this->assertEquals($c11b->get_id(), $rc->get_relatedcompetencyid());
3236
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());
3241 $uc2->delete();
3242
3243 $this->assertTrue(api::delete_competency($c1a->get_id()));
3244 $this->assertFalse(competency::record_exists($c1a->get_id()));
3245
3246 // Check that on delete, we reset the rule on parent competency.
3247 $c1->read();
3248 $this->assertNull($c1->get_ruletype());
3249 $this->assertNull($c1->get_ruletype());
3250 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
3251
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()));
3256
3257 // Check if evidence are also deleted.
67bc0eaf 3258 $this->assertEquals(0, \core_competency\user_evidence_competency::count_records(array('competencyid' => $c11b->get_id())));
9a325eda
IT
3259
3260 // Check if related conpetency relation is deleted.
3261 $this->assertEquals(0, count(api::list_related_competencies($c2->get_id())));
3262
3263 // Delete a simple competency.
3264 $this->assertTrue(api::delete_competency($c2->get_id()));
3265 $this->assertFalse(competency::record_exists($c2->get_id()));
3266 }
3267
3268 public function test_delete_competency_used_in_plan() {
3269 $this->resetAfterTest(true);
3270 $dg = $this->getDataGenerator();
922634d3 3271 $lpg = $dg->get_plugin_generator('core_competency');
9a325eda
IT
3272 $this->setAdminUser();
3273
3274 $u1 = $dg->create_user();
3275
3276 $plan = $lpg->create_plan((object) array('userid' => $u1->id));
3277
3278 $f1 = $lpg->create_framework();
3279 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
3280 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
3281 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
3282 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a->get_id()));
3283 $c11b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
3284 $c12b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
3285
3286 // Add competency to plan.
3287 $pc = $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c11b->get_id()));
3288 // We can not delete a competency , if competency or competency children is associated to plan.
3289 $this->assertFalse(api::delete_competency($c1a->get_id()));
3290
3291 // We can delete the competency if we remove the competency from the plan.
3292 $pc->delete();
3293
3294 $this->assertTrue(api::delete_competency($c1a->get_id()));
3295 $this->assertFalse(competency::record_exists($c1a->get_id()));
3296 $this->assertFalse(competency::record_exists($c1b->get_id()));
3297 $this->assertFalse(competency::record_exists($c11b->get_id()));
3298 $this->assertFalse(competency::record_exists($c12b->get_id()));
3299 }
3300
3301 public function test_delete_competency_used_in_usercompetency() {
3302 $this->resetAfterTest(true);
3303 $dg = $this->getDataGenerator();
922634d3 3304 $lpg = $dg->get_plugin_generator('core_competency');
9a325eda
IT
3305 $this->setAdminUser();
3306
3307 $u1 = $dg->create_user();
3308
3309 $