MDL-52758 cbe: Improve formatting of course competencies page.
[moodle.git] / admin / tool / lp / 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 *
20 * @package tool_lp
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
28use tool_lp\api;
20c2fe3e 29use tool_lp\competency;
9373acf6 30use tool_lp\evidence;
4de456cd 31use tool_lp\user_competency;
a8902ee2 32use tool_lp\plan;
f610a957
FM
33
34/**
35 * API tests.
36 *
37 * @package tool_lp
38 * @copyright 2015 Frédéric Massart - FMCorz.net
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 */
41class tool_lp_api_testcase extends advanced_testcase {
42
43 public function test_get_framework_related_contexts() {
44 $this->resetAfterTest(true);
45 $dg = $this->getDataGenerator();
46 $cat1 = $dg->create_category();
47 $cat2 = $dg->create_category(array('parent' => $cat1->id));
48 $cat3 = $dg->create_category(array('parent' => $cat2->id));
f0da26a4 49 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
f610a957
FM
50
51 $cat1ctx = context_coursecat::instance($cat1->id);
52 $cat2ctx = context_coursecat::instance($cat2->id);
53 $cat3ctx = context_coursecat::instance($cat3->id);
54 $sysctx = context_system::instance();
55
56 $expected = array($cat1ctx->id => $cat1ctx);
f0da26a4 57 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
f610a957
FM
58
59 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
f0da26a4 60 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
f610a957
FM
61
62 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
f0da26a4 63 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
f610a957
FM
64 }
65
66 public function test_get_framework_related_contexts_with_capabilities() {
67 $this->resetAfterTest(true);
68 $dg = $this->getDataGenerator();
69 $user = $dg->create_user();
70 $cat1 = $dg->create_category();
71 $cat2 = $dg->create_category(array('parent' => $cat1->id));
72 $cat3 = $dg->create_category(array('parent' => $cat2->id));
f0da26a4 73 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
f610a957
FM
74
75 $cat1ctx = context_coursecat::instance($cat1->id);
76 $cat2ctx = context_coursecat::instance($cat2->id);
77 $cat3ctx = context_coursecat::instance($cat3->id);
78 $sysctx = context_system::instance();
79
80 $roleallow = create_role('Allow', 'allow', 'Allow read');
81 assign_capability('tool/lp:competencyread', CAP_ALLOW, $roleallow, $sysctx->id);
82 role_assign($roleallow, $user->id, $sysctx->id);
83
84 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
85 assign_capability('tool/lp:competencyread', CAP_PROHIBIT, $roleprevent, $sysctx->id);
86 role_assign($roleprevent, $user->id, $cat2ctx->id);
87
88 accesslib_clear_all_caches_for_unit_testing();
89 $this->setUser($user);
90 $this->assertFalse(has_capability('tool/lp:competencyread', $cat2ctx));
91
92 $requiredcap = array('tool/lp:competencyread');
93
94 $expected = array();
f0da26a4 95 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
f610a957
FM
96
97 $expected = array($cat1ctx->id => $cat1ctx);
f0da26a4 98 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
f610a957
FM
99
100 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
f0da26a4 101 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
f610a957 102 }
f0da26a4
FM
103
104 public function test_get_template_related_contexts() {
105 $this->resetAfterTest(true);
106 $dg = $this->getDataGenerator();
107 $cat1 = $dg->create_category();
108 $cat2 = $dg->create_category(array('parent' => $cat1->id));
109 $cat3 = $dg->create_category(array('parent' => $cat2->id));
110 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
111
112 $cat1ctx = context_coursecat::instance($cat1->id);
113 $cat2ctx = context_coursecat::instance($cat2->id);
114 $cat3ctx = context_coursecat::instance($cat3->id);
115 $sysctx = context_system::instance();
116
117 $expected = array($cat1ctx->id => $cat1ctx);
118 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'self'));
119
120 $expected = array($cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx, $cat3ctx->id => $cat3ctx);
121 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children'));
122
123 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx, $cat2ctx->id => $cat2ctx);
124 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents'));
125 }
126
127 public function test_get_template_related_contexts_with_capabilities() {
128 $this->resetAfterTest(true);
129 $dg = $this->getDataGenerator();
130 $user = $dg->create_user();
131 $cat1 = $dg->create_category();
132 $cat2 = $dg->create_category(array('parent' => $cat1->id));
133 $cat3 = $dg->create_category(array('parent' => $cat2->id));
134 $c1 = $dg->create_course(array('category' => $cat2->id)); // This context should not be returned.
135
136 $cat1ctx = context_coursecat::instance($cat1->id);
137 $cat2ctx = context_coursecat::instance($cat2->id);
138 $cat3ctx = context_coursecat::instance($cat3->id);
139 $sysctx = context_system::instance();
140
141 $roleallow = create_role('Allow', 'allow', 'Allow read');
142 assign_capability('tool/lp:templateread', CAP_ALLOW, $roleallow, $sysctx->id);
143 role_assign($roleallow, $user->id, $sysctx->id);
144
145 $roleprevent = create_role('Prevent', 'prevent', 'Prevent read');
146 assign_capability('tool/lp:templateread', CAP_PROHIBIT, $roleprevent, $sysctx->id);
147 role_assign($roleprevent, $user->id, $cat2ctx->id);
148
149 accesslib_clear_all_caches_for_unit_testing();
150 $this->setUser($user);
151 $this->assertFalse(has_capability('tool/lp:templateread', $cat2ctx));
152
153 $requiredcap = array('tool/lp:templateread');
154
155 $expected = array();
156 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'self', $requiredcap));
157
158 $expected = array($cat1ctx->id => $cat1ctx);
159 $this->assertEquals($expected, api::get_related_contexts($cat1ctx, 'children', $requiredcap));
160
161 $expected = array($sysctx->id => $sysctx, $cat1ctx->id => $cat1ctx);
162 $this->assertEquals($expected, api::get_related_contexts($cat2ctx, 'parents', $requiredcap));
163 }
164
ec324dc6
FM
165 /**
166 * Test updating a template.
167 */
168 public function test_update_template() {
169 $cat = $this->getDataGenerator()->create_category();
170 $this->resetAfterTest(true);
171 $this->setAdminUser();
172
173 $syscontext = context_system::instance();
174 $template = api::create_template((object) array('shortname' => 'testing', 'contextid' => $syscontext->id));
175
176 $this->assertEquals('testing', $template->get_shortname());
177 $this->assertEquals($syscontext->id, $template->get_contextid());
178
179 // Simple update.
180 api::update_template((object) array('id' => $template->get_id(), 'shortname' => 'success'));
181 $template = api::read_template($template->get_id());
182 $this->assertEquals('success', $template->get_shortname());
183
184 // Trying to change the context.
185 $this->setExpectedException('coding_exception');
186 api::update_template((object) array('id' => $template->get_id(), 'contextid' => context_coursecat::instance($cat->id)));
187 }
188
b3979696
IT
189 /**
190 * Test listing framework with order param.
191 */
192 public function test_list_frameworks() {
193 $this->resetAfterTest(true);
194 $this->setAdminUser();
bf61cd0c 195 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
b3979696
IT
196
197 // Create a list of frameworks.
bf61cd0c
FM
198 $framework1 = $lpg->create_framework(array(
199 'shortname' => 'shortname_a',
200 'idnumber' => 'idnumber_c',
201 'description' => 'description',
202 'descriptionformat' => FORMAT_HTML,
203 'visible' => true,
204 'contextid' => context_system::instance()->id
205 ));
206
207 $framework2 = $lpg->create_framework(array(
208 'shortname' => 'shortname_b',
209 'idnumber' => 'idnumber_a',
210 'description' => 'description',
211 'descriptionformat' => FORMAT_HTML,
212 'visible' => true,
213 'contextid' => context_system::instance()->id
214 ));
215
216 $framework3 = $lpg->create_framework(array(
217 'shortname' => 'shortname_c',
218 'idnumber' => 'idnumber_b',
219 'description' => 'description',
220 'descriptionformat' => FORMAT_HTML,
221 'visible' => true,
222 'contextid' => context_system::instance()->id
223 ));
b3979696
IT
224
225 // Get frameworks list order by shortname desc.
226 $result = api::list_frameworks('shortname', 'DESC', null, 3, context_system::instance());
227
1896274f
FM
228 $f = (object) array_shift($result);
229 $this->assertEquals($framework3->get_id(), $f->get_id());
230 $f = (object) array_shift($result);
231 $this->assertEquals($framework2->get_id(), $f->get_id());
232 $f = (object) array_shift($result);
233 $this->assertEquals($framework1->get_id(), $f->get_id());
b3979696
IT
234
235 // Get frameworks list order by idnumber asc.
236 $result = api::list_frameworks('idnumber', 'ASC', null, 3, context_system::instance());
237
1896274f
FM
238 $f = (object) array_shift($result);
239 $this->assertEquals($framework2->get_id(), $f->get_id());
240 $f = (object) array_shift($result);
241 $this->assertEquals($framework3->get_id(), $f->get_id());
242 $f = (object) array_shift($result);
243 $this->assertEquals($framework1->get_id(), $f->get_id());
b3979696
IT
244 }
245
c61db7bb
IT
246 /**
247 * Test duplicate a framework.
248 */
249 public function test_duplicate_framework() {
250 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
251 $this->resetAfterTest(true);
252 $this->setAdminUser();
253
254 $syscontext = context_system::instance();
255 $params = array(
256 'shortname' => 'shortname_a',
257 'idnumber' => 'idnumber_c',
258 'description' => 'description',
259 'descriptionformat' => FORMAT_HTML,
260 'visible' => true,
261 'contextid' => $syscontext->id
262 );
263 $framework = $lpg->create_framework($params);
264 $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
265 $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
266 $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
267 $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
4c4a8d41
IT
268 $competency41 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
269 'parentid' => $competency4->get_id())
270 );
271 $competency42 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
272 'parentid' => $competency4->get_id())
273 );
c61db7bb
IT
274 $competencyidnumbers = array($competency1->get_idnumber(),
275 $competency2->get_idnumber(),
276 $competency3->get_idnumber(),
4c4a8d41
IT
277 $competency4->get_idnumber(),
278 $competency41->get_idnumber(),
279 $competency42->get_idnumber()
c61db7bb
IT
280 );
281
4c4a8d41
IT
282 $config = json_encode(array(
283 'base' => array('points' => 4),
284 'competencies' => array(
285 array('id' => $competency41->get_id(), 'points' => 3, 'required' => 0),
286 array('id' => $competency42->get_id(), 'points' => 2, 'required' => 1),
287 )
288 ));
289 $competency4->set_ruletype('tool_lp\competency_rule_points');
290 $competency4->set_ruleoutcome(\tool_lp\competency::OUTCOME_EVIDENCE);
291 $competency4->set_ruleconfig($config);
292 $competency4->update();
293
c61db7bb
IT
294 api::add_related_competency($competency1->get_id(), $competency2->get_id());
295 api::add_related_competency($competency3->get_id(), $competency4->get_id());
296
297 $frameworkduplicated1 = api::duplicate_framework($framework->get_id());
298 $frameworkduplicated2 = api::duplicate_framework($framework->get_id());
299
300 $this->assertEquals($framework->get_idnumber().'_1', $frameworkduplicated1->get_idnumber());
301 $this->assertEquals($framework->get_idnumber().'_2', $frameworkduplicated2->get_idnumber());
302
303 $competenciesfr1 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated1->get_id()));
304 $competenciesfr2 = api::list_competencies(array('competencyframeworkid' => $frameworkduplicated2->get_id()));
305
306 $competencyidsfr1 = array();
307 $competencyidsfr2 = array();
308
309 foreach ($competenciesfr1 as $cmp) {
310 $competencyidsfr1[] = $cmp->get_idnumber();
311 }
312 foreach ($competenciesfr2 as $cmp) {
313 $competencyidsfr2[] = $cmp->get_idnumber();
314 }
315
316 $this->assertEmpty(array_diff($competencyidsfr1, $competencyidnumbers));
317 $this->assertEmpty(array_diff($competencyidsfr2, $competencyidnumbers));
4c4a8d41
IT
318 $this->assertCount(6, $competenciesfr1);
319 $this->assertCount(6, $competenciesfr2);
c61db7bb
IT
320
321 // Test the related competencies.
322 reset($competenciesfr1);
323 $compduplicated1 = current($competenciesfr1);
324 $relatedcompetencies = $compduplicated1->get_related_competencies();
325 $comprelated = current($relatedcompetencies);
326 $this->assertEquals($comprelated->get_idnumber(), $competency2->get_idnumber());
5a4ee001 327
4c4a8d41
IT
328 // Check if config rule have been ported correctly.
329 $competency4duplicated = competency::get_record(array(
330 'idnumber' => $competency4->get_idnumber(),
331 'competencyframeworkid' => $frameworkduplicated2->get_id()
332 ));
333 $configduplicated = json_decode($competency4duplicated->get_ruleconfig(), true);
334 $configorigin = json_decode($config, true);
335 // Check that the 2 config have the same base.
336 $this->assertEquals($configorigin['base'], $configduplicated['base']);
337 $this->assertEquals(count($configorigin['competencies']), count($configduplicated['competencies']));
338 $competenciesidsrules = array();
339 foreach ($configduplicated['competencies'] as $key => $value) {
340 // Check that the only difference between the 2 config is id competency.
341 $this->assertEquals(1, count(array_diff($value, $configorigin['competencies'][$key])));
342 $competenciesidsrules[] = $value['id'];
343 }
344 $this->assertTrue($competency4duplicated->is_parent_of($competenciesidsrules));
5a4ee001 345
c61db7bb
IT
346 }
347
58405003
IT
348 /**
349 * Test update plan.
350 */
351 public function test_update_plan() {
352 $this->resetAfterTest(true);
353 $dg = $this->getDataGenerator();
354 $usermanageowndraft = $dg->create_user();
355 $usermanageown = $dg->create_user();
356 $usermanagedraft = $dg->create_user();
357 $usermanage = $dg->create_user();
358
359 $syscontext = context_system::instance();
360
361 // Creating specific roles.
362 $manageowndraftrole = $dg->create_role(array(
363 'name' => 'User manage own draft',
364 'shortname' => 'manage-own-draft'
365 ));
366 $manageownrole = $dg->create_role(array(
367 'name' => 'User manage own',
368 'shortname' => 'manage-own'
369 ));
370 $managedraftrole = $dg->create_role(array(
371 'name' => 'User manage draft',
372 'shortname' => 'manage-draft'
373 ));
374 $managerole = $dg->create_role(array(
375 'name' => 'User manage',
376 'shortname' => 'manage'
377 ));
378
379 assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
380 assign_capability('tool/lp:planviewowndraft', CAP_ALLOW, $manageowndraftrole, $syscontext->id);
381
382 assign_capability('tool/lp:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
383 assign_capability('tool/lp:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
384
385 assign_capability('tool/lp:planmanagedraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
386 assign_capability('tool/lp:planviewdraft', CAP_ALLOW, $managedraftrole, $syscontext->id);
387
388 assign_capability('tool/lp:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
389 assign_capability('tool/lp:planview', CAP_ALLOW, $managerole, $syscontext->id);
390
391 $dg->role_assign($manageowndraftrole, $usermanageowndraft->id, $syscontext->id);
392 $dg->role_assign($manageownrole, $usermanageown->id, $syscontext->id);
393 $dg->role_assign($managedraftrole, $usermanagedraft->id, $syscontext->id);
394 $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
395
396 // Create first learning plan with user create draft.
397 $this->setUser($usermanageowndraft);
398 $plan = array (
399 'name' => 'plan own draft',
400 'description' => 'plan own draft',
401 'userid' => $usermanageowndraft->id
402 );
403 $plan = api::create_plan((object)$plan);
404 $record = $plan->to_record();
405 $record->name = 'plan own draft modified';
406
407 // Check if user create draft can edit the plan name.
408 $plan = api::update_plan($record);
409 $this->assertInstanceOf('\tool_lp\plan', $plan);
410
3c230247 411 // The status cannot be changed in this method.
58405003
IT
412 $record->status = \tool_lp\plan::STATUS_ACTIVE;
413 try {
414 $plan = api::update_plan($record);
3c230247
FM
415 $this->fail('Updating the status is not allowed.');
416 } catch (coding_exception $e) {
417 $this->assertRegExp('/To change the status of a plan use the appropriate methods./', $e->getMessage());
58405003
IT
418 }
419
420 // Test when user with manage own plan capability try to edit other user plan.
421 $record->status = \tool_lp\plan::STATUS_DRAFT;
422 $record->name = 'plan create draft modified 2';
423 $this->setUser($usermanageown);
424 try {
425 $plan = api::update_plan($record);
426 $this->fail('User with manage own plan capability can only edit his own plan.');
427 } catch (required_capability_exception $e) {
428 $this->assertTrue(true);
429 }
430
431 // User with manage plan capability cannot edit the other user plans with status draft.
432 $this->setUser($usermanage);
3c230247 433 $record->name = 'plan create draft modified 3';
58405003
IT
434 try {
435 $plan = api::update_plan($record);
436 $this->fail('User with manage plan capability cannot edit the other user plans with status draft');
437 } catch (required_capability_exception $e) {
438 $this->assertTrue(true);
439 }
440
441 // User with manage draft capability can edit other user's learning plan if the status is draft.
442 $this->setUser($usermanagedraft);
443 $record->status = \tool_lp\plan::STATUS_DRAFT;
444 $record->name = 'plan manage draft modified 3';
445 $plan = api::update_plan($record);
446 $this->assertInstanceOf('\tool_lp\plan', $plan);
447
448 // User with manage plan capability can create/edit learning plan if status is active/complete.
449 $this->setUser($usermanage);
450 $plan = array (
451 'name' => 'plan create',
452 'description' => 'plan create',
453 'userid' => $usermanage->id,
454 'status' => \tool_lp\plan::STATUS_ACTIVE
455 );
456 $plan = api::create_plan((object)$plan);
5bfab685
FM
457
458 // Silently transition to complete status to avoid errors about transitioning to complete.
459 $plan->set_status(\tool_lp\plan::STATUS_COMPLETE);
460 $plan->update();
461
58405003
IT
462 $record = $plan->to_record();
463 $record->name = 'plan create own modified';
d805cc37
IT
464 try {
465 api::update_plan($record);
466 $this->fail('Completed plan can not be edited');
467 } catch (coding_exception $e) {
468 $this->assertTrue(true);
469 }
58405003
IT
470 }
471
2388d46d
FM
472 public function test_create_plan_from_template() {
473 $this->resetAfterTest(true);
474 $this->setAdminUser();
475
476 $u1 = $this->getDataGenerator()->create_user();
477 $tpl = $this->getDataGenerator()->get_plugin_generator('tool_lp')->create_template();
478
479 // Creating a new plan.
480 $plan = api::create_plan_from_template($tpl, $u1->id);
481 $record = $plan->to_record();
482 $this->assertInstanceOf('\tool_lp\plan', $plan);
483 $this->assertTrue(\tool_lp\plan::record_exists($plan->get_id()));
484 $this->assertEquals($tpl->get_id(), $plan->get_templateid());
485 $this->assertEquals($u1->id, $plan->get_userid());
486 $this->assertTrue($plan->is_based_on_template());
487
488 // Creating a plan that already exists.
489 $plan = api::create_plan_from_template($tpl, $u1->id);
490 $this->assertFalse($plan);
491
492 // Check that api::create_plan cannot be used.
493 $this->setExpectedException('coding_exception');
494 unset($record->id);
495 $plan = api::create_plan($record);
496 }
497
4de877eb
FM
498 public function test_update_plan_based_on_template() {
499 $this->resetAfterTest(true);
500 $dg = $this->getDataGenerator();
501 $lpg = $dg->get_plugin_generator('tool_lp');
502 $u1 = $dg->create_user();
503 $u2 = $dg->create_user();
504
505 $this->setAdminUser();
506 $tpl1 = $lpg->create_template();
507 $tpl2 = $lpg->create_template();
508 $up1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id()));
509 $up2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => null));
510
511 try {
512 // Trying to remove the template dependency.
513 $record = $up1->to_record();
514 $record->templateid = null;
515 api::update_plan($record);
516 $this->fail('A plan cannot be unlinked using api::update_plan()');
517 } catch (coding_exception $e) {
518 }
519
520 try {
521 // Trying to switch to another template.
522 $record = $up1->to_record();
523 $record->templateid = $tpl2->get_id();
524 api::update_plan($record);
525 $this->fail('A plan cannot be moved to another template.');
526 } catch (coding_exception $e) {
527 }
528
529 try {
530 // Trying to switch to using a template.
531 $record = $up2->to_record();
532 $record->templateid = $tpl1->get_id();
533 api::update_plan($record);
534 $this->fail('A plan cannot be update to use a template.');
535 } catch (coding_exception $e) {
536 }
537 }
538
6d2c2e86
FM
539 public function test_unlink_plan_from_template() {
540 $this->resetAfterTest(true);
541 $dg = $this->getDataGenerator();
542 $lpg = $dg->get_plugin_generator('tool_lp');
543 $u1 = $dg->create_user();
544 $u2 = $dg->create_user();
545
546 $this->setAdminUser();
547 $f1 = $lpg->create_framework();
548 $f2 = $lpg->create_framework();
549 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
550 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get_id()));
551 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
552
553 $tpl1 = $lpg->create_template();
554 $tpl2 = $lpg->create_template();
555
556 $tplc1a = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1a->get_id(),
557 'sortorder' => 9));
558 $tplc1b = $lpg->create_template_competency(array('templateid' => $tpl1->get_id(), 'competencyid' => $c1b->get_id(),
559 'sortorder' => 8));
560 $tplc2a = $lpg->create_template_competency(array('templateid' => $tpl2->get_id(), 'competencyid' => $c2a->get_id()));
561
a8902ee2 562 $plan1 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_ACTIVE));
6d2c2e86 563 $plan2 = $lpg->create_plan(array('userid' => $u2->id, 'templateid' => $tpl2->get_id()));
a8902ee2 564 $plan3 = $lpg->create_plan(array('userid' => $u1->id, 'templateid' => $tpl1->get_id(), 'status' => plan::STATUS_COMPLETE));
6d2c2e86
FM
565
566 // Check that we have what we expect at this stage.
567 $this->assertEquals(2, \tool_lp\template_competency::count_records(array('templateid' => $tpl1->get_id())));
568 $this->assertEquals(1, \tool_lp\template_competency::count_records(array('templateid' => $tpl2->get_id())));
569 $this->assertEquals(0, \tool_lp\plan_competency::count_records(array('planid' => $plan1->get_id())));
570 $this->assertEquals(0, \tool_lp\plan_competency::count_records(array('planid' => $plan2->get_id())));
571 $this->assertTrue($plan1->is_based_on_template());
572 $this->assertTrue($plan2->is_based_on_template());
573
574 // Let's do this!
575 $tpl1comps = \tool_lp\template_competency::list_competencies($tpl1->get_id(), true);
576 $tpl2comps = \tool_lp\template_competency::list_competencies($tpl2->get_id(), true);
577
578 api::unlink_plan_from_template($plan1);
579
580 $plan1->read();
581 $plan2->read();
582 $this->assertCount(2, $tpl1comps);
583 $this->assertCount(1, $tpl2comps);
584 $this->assertEquals(2, \tool_lp\template_competency::count_records(array('templateid' => $tpl1->get_id())));
585 $this->assertEquals(1, \tool_lp\template_competency::count_records(array('templateid' => $tpl2->get_id())));
586 $this->assertEquals(2, \tool_lp\plan_competency::count_records(array('planid' => $plan1->get_id())));
587 $this->assertEquals(0, \tool_lp\plan_competency::count_records(array('planid' => $plan2->get_id())));
588 $this->assertFalse($plan1->is_based_on_template());
589 $this->assertEquals($tpl1->get_id(), $plan1->get_origtemplateid());
590 $this->assertTrue($plan2->is_based_on_template());
591 $this->assertEquals(null, $plan2->get_origtemplateid());
592
a8902ee2
SG
593 // Check we can unlink draft plan.
594 try {
595 api::unlink_plan_from_template($plan2);
596 } catch (coding_exception $e) {
597 $this->fail('Fail to unlink draft plan.');
598 }
599
600 // Check we can not unlink completed plan.
601 try {
602 api::unlink_plan_from_template($plan3);
603 $this->fail('We can not unlink completed plan.');
604 } catch (coding_exception $e) {
605 }
606
6d2c2e86
FM
607 // Even the order remains.
608 $plan1comps = \tool_lp\plan_competency::list_competencies($plan1->get_id());
609 $before = reset($tpl1comps);
610 $after = reset($plan1comps);
611 $this->assertEquals($before->get_id(), $after->get_id());
612 $this->assertEquals($before->get_sortorder(), $after->get_sortorder());
613 $before = next($tpl1comps);
614 $after = next($plan1comps);
615 $this->assertEquals($before->get_id(), $after->get_id());
616 $this->assertEquals($before->get_sortorder(), $after->get_sortorder());
617 }
618
c7999f6d
FM
619 public function test_update_template_updates_plans() {
620 $this->resetAfterTest(true);
621 $this->setAdminUser();
622
623 $dg = $this->getDataGenerator();
624 $u1 = $dg->create_user();
625 $u2 = $dg->create_user();
626 $lpg = $dg->get_plugin_generator('tool_lp');
627 $tpl1 = $lpg->create_template();
628 $tpl2 = $lpg->create_template();
629
c7999f6d
FM
630 // Create plans with data not matching templates.
631 $time = time();
632 $plan1 = $lpg->create_plan(array('templateid' => $tpl1->get_id(), 'userid' => $u1->id,
633 'name' => 'Not good name', 'duedate' => $time + 3600, 'description' => 'Ahah', 'descriptionformat' => FORMAT_MARKDOWN));
634 $plan2 = $lpg->create_plan(array('templateid' => $tpl1->get_id(), 'userid' => $u2->id,
635 'name' => 'Not right name', 'duedate' => $time + 3601, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
636 $plan3 = $lpg->create_plan(array('templateid' => $tpl2->get_id(), 'userid' => $u1->id,
637 'name' => 'Not sweet name', 'duedate' => $time + 3602, 'description' => 'Ahah', 'descriptionformat' => FORMAT_PLAIN));
638
639 // Prepare our expectations.
640 $plan1->read();
641 $plan2->read();
642 $plan3->read();
643
644 $this->assertEquals($tpl1->get_id(), $plan1->get_templateid());
645 $this->assertEquals($tpl1->get_id(), $plan2->get_templateid());
646 $this->assertEquals($tpl2->get_id(), $plan3->get_templateid());
647 $this->assertNotEquals($tpl1->get_shortname(), $plan1->get_name());
648 $this->assertNotEquals($tpl1->get_shortname(), $plan2->get_name());
649 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
650 $this->assertNotEquals($tpl1->get_description(), $plan1->get_description());
651 $this->assertNotEquals($tpl1->get_description(), $plan2->get_description());
652 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
653 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
654 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
655 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
656 $this->assertNotEquals($tpl1->get_duedate(), $plan1->get_duedate());
657 $this->assertNotEquals($tpl1->get_duedate(), $plan2->get_duedate());
658 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
659
660 // Update the template without changing critical fields does not update the plans.
661 $data = $tpl1->to_record();
662 $data->visible = 0;
663 api::update_template($data);
664 $this->assertNotEquals($tpl1->get_shortname(), $plan1->get_name());
665 $this->assertNotEquals($tpl1->get_shortname(), $plan2->get_name());
666 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
667 $this->assertNotEquals($tpl1->get_description(), $plan1->get_description());
668 $this->assertNotEquals($tpl1->get_description(), $plan2->get_description());
669 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
670 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
671 $this->assertNotEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
672 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
673 $this->assertNotEquals($tpl1->get_duedate(), $plan1->get_duedate());
674 $this->assertNotEquals($tpl1->get_duedate(), $plan2->get_duedate());
675 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
676
677 // Now really update the template.
678 $data = $tpl1->to_record();
679 $data->shortname = 'Awesome!';
680 $data->description = 'This is too awesome!';
681 $data->descriptionformat = FORMAT_HTML;
a967d2aa 682 $data->duedate = $time + 200;
c7999f6d
FM
683 api::update_template($data);
684 $tpl1->read();
685
686 // Now confirm that the right plans were updated.
687 $plan1->read();
688 $plan2->read();
689 $plan3->read();
690
691 $this->assertEquals($tpl1->get_id(), $plan1->get_templateid());
692 $this->assertEquals($tpl1->get_id(), $plan2->get_templateid());
693 $this->assertEquals($tpl2->get_id(), $plan3->get_templateid());
694
695 $this->assertEquals($tpl1->get_shortname(), $plan1->get_name());
696 $this->assertEquals($tpl1->get_shortname(), $plan2->get_name());
697 $this->assertNotEquals($tpl2->get_shortname(), $plan3->get_name());
698 $this->assertEquals($tpl1->get_description(), $plan1->get_description());
699 $this->assertEquals($tpl1->get_description(), $plan2->get_description());
700 $this->assertNotEquals($tpl2->get_description(), $plan3->get_description());
701 $this->assertEquals($tpl1->get_descriptionformat(), $plan1->get_descriptionformat());
702 $this->assertEquals($tpl1->get_descriptionformat(), $plan2->get_descriptionformat());
703 $this->assertNotEquals($tpl2->get_descriptionformat(), $plan3->get_descriptionformat());
704 $this->assertEquals($tpl1->get_duedate(), $plan1->get_duedate());
705 $this->assertEquals($tpl1->get_duedate(), $plan2->get_duedate());
706 $this->assertNotEquals($tpl2->get_duedate(), $plan3->get_duedate());
707 }
708
5bfab685
FM
709 /**
710 * Test that the method to complete a plan.
711 */
712 public function test_complete_plan() {
713 global $DB;
714
715 $this->resetAfterTest(true);
716 $this->setAdminUser();
717 $dg = $this->getDataGenerator();
718 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
719 $user = $dg->create_user();
720
721 // Create a framework and assign competencies.
722 $framework = $lpg->create_framework();
723 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
724 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
725 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
d3275795 726 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
5bfab685
FM
727
728 // Create two plans and assign competencies.
729 $plan = $lpg->create_plan(array('userid' => $user->id));
730 $otherplan = $lpg->create_plan(array('userid' => $user->id));
731
732 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c1->get_id()));
733 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c2->get_id()));
734 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c3->get_id()));
735 $lpg->create_plan_competency(array('planid' => $otherplan->get_id(), 'competencyid' => $c1->get_id()));
736
737 $uclist = array(
738 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
739 'proficiency' => true, 'grade' => 1 )),
740 $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
741 'proficiency' => false, 'grade' => 2 ))
742 );
743
744 $this->assertEquals(2, \tool_lp\user_competency::count_records());
745 $this->assertEquals(0, \tool_lp\user_competency_plan::count_records());
746
747 // Change status of the plan to complete.
748 api::complete_plan($plan);
749
750 // Check that user competencies are now in user_competency_plan objects and still in user_competency.
751 $this->assertEquals(2, \tool_lp\user_competency::count_records());
752 $this->assertEquals(3, \tool_lp\user_competency_plan::count_records());
753
754 $usercompetenciesplan = \tool_lp\user_competency_plan::get_records();
755
756 $this->assertEquals($uclist[0]->get_userid(), $usercompetenciesplan[0]->get_userid());
757 $this->assertEquals($uclist[0]->get_competencyid(), $usercompetenciesplan[0]->get_competencyid());
758 $this->assertEquals($uclist[0]->get_proficiency(), (bool) $usercompetenciesplan[0]->get_proficiency());
759 $this->assertEquals($uclist[0]->get_grade(), $usercompetenciesplan[0]->get_grade());
760 $this->assertEquals($plan->get_id(), $usercompetenciesplan[0]->get_planid());
761
762 $this->assertEquals($uclist[1]->get_userid(), $usercompetenciesplan[1]->get_userid());
763 $this->assertEquals($uclist[1]->get_competencyid(), $usercompetenciesplan[1]->get_competencyid());
764 $this->assertEquals($uclist[1]->get_proficiency(), (bool) $usercompetenciesplan[1]->get_proficiency());
765 $this->assertEquals($uclist[1]->get_grade(), $usercompetenciesplan[1]->get_grade());
766 $this->assertEquals($plan->get_id(), $usercompetenciesplan[1]->get_planid());
767
768 $this->assertEquals($user->id, $usercompetenciesplan[2]->get_userid());
769 $this->assertEquals($c3->get_id(), $usercompetenciesplan[2]->get_competencyid());
770 $this->assertNull($usercompetenciesplan[2]->get_proficiency());
771 $this->assertNull($usercompetenciesplan[2]->get_grade());
772 $this->assertEquals($plan->get_id(), $usercompetenciesplan[2]->get_planid());
773
d3275795
SG
774 // Check we can not add competency to completed plan.
775 try {
776 api::add_competency_to_plan($plan->get_id(), $c4->get_id());
777 $this->fail('We can not add competency to completed plan.');
778 } catch (coding_exception $e) {
779 }
780
781 // Check we can not remove competency to completed plan.
782 try {
783 api::remove_competency_from_plan($plan->get_id(), $c3->get_id());
784 $this->fail('We can not remove competency to completed plan.');
785 } catch (coding_exception $e) {
786 }
787
5bfab685
FM
788 // Completing a plan that is completed throws an exception.
789 $this->setExpectedException('coding_exception');
790 api::complete_plan($plan);
791 }
792
3c230247
FM
793 /**
794 * Set-up the workflow data (review, active, ...).
795 *
796 * @return array
797 */
798 protected function setup_workflow_data() {
799 $this->resetAfterTest();
800
801 $dg = $this->getDataGenerator();
802 $user = $dg->create_user();
803 $reviewer = $dg->create_user();
804 $otheruser = $dg->create_user();
805
806 $syscontext = context_system::instance();
807 $userrole = $dg->create_role();
808 $reviewerrole = $dg->create_role();
809 $otheruserrole = $dg->create_role();
810
811 assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $userrole, $syscontext->id);
812 assign_capability('tool/lp:planmanage', CAP_ALLOW, $reviewerrole, $syscontext->id);
813 assign_capability('tool/lp:planviewdraft', CAP_ALLOW, $reviewerrole, $syscontext->id);
814 $dg->role_assign($userrole, $user->id, $syscontext->id);
815 $dg->role_assign($reviewerrole, $reviewer->id, $syscontext->id);
816 accesslib_clear_all_caches_for_unit_testing();
817
818 $lpg = $dg->get_plugin_generator('tool_lp');
819 $tpl = $lpg->create_template();
820 $plan = $lpg->create_plan(array('userid' => $user->id));
821 $tplplan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tpl->get_id()));
822
823 return array(
824 'dg' => $dg,
825 'lpg' => $lpg,
826 'user' => $user,
827 'reviewer' => $reviewer,
828 'otheruser' => $otheruser,
829 'plan' => $plan,
830 'tplplan' => $tplplan,
831 );
832 }
833
834 /**
835 * Testing requesting the review of a plan.
836 */
837 public function test_plan_request_review() {
838 $data = $this->setup_workflow_data();
839 extract($data);
840
841 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
842 $this->assertEquals(plan::STATUS_DRAFT, $tplplan->get_status());
843
844 // Foreign user cannot do anything.
845 $this->setUser($otheruser);
846 try {
847 api::plan_request_review($plan);
848 $this->fail('The user can not read the plan.');
849 } catch (required_capability_exception $e) {
850 $this->assertEquals('nopermissions', $e->errorcode);
851 }
852
853 // Can not change a plan based on a template.
854 $this->setUser($user);
855 try {
856 api::plan_request_review($tplplan);
857 $this->fail('The plan is based on a template.');
858 } catch (coding_exception $e) {
859 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
860 }
861
862 // Can not send for review when not draft.
863 $this->setUser($user);
864 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
865 try {
866 api::plan_request_review($plan);
867 $this->fail('The plan cannot be sent for review at this stage.');
868 } catch (coding_exception $e) {
869 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
870 }
871
872 // Can not send for review when not draft.
873 $this->setUser($user);
874 $plan->set_status(plan::STATUS_ACTIVE);
875 try {
876 api::plan_request_review($plan);
877 $this->fail('The plan cannot be sent for review at this stage.');
878 } catch (coding_exception $e) {
879 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
880 }
881
882 // Can not send for review when not draft.
883 $this->setUser($user);
884 $plan->set_status(plan::STATUS_IN_REVIEW);
885 try {
886 api::plan_request_review($plan);
887 $this->fail('The plan cannot be sent for review at this stage.');
888 } catch (coding_exception $e) {
889 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
890 }
891
892 // Can not send for review when not draft.
893 $this->setUser($user);
894 $plan->set_status(plan::STATUS_COMPLETE);
895 try {
896 api::plan_request_review($plan);
897 $this->fail('The plan cannot be sent for review at this stage.');
898 } catch (coding_exception $e) {
899 $this->assertRegExp('/The plan cannot be sent for review at this stage./', $e->getMessage());
900 }
901
902 // Sending for review as a reviewer.
903 $this->setUser($reviewer);
904 $plan->set_status(plan::STATUS_DRAFT);
905 try {
906 api::plan_request_review($plan);
907 $this->fail('The user can not request a review.');
908 } catch (required_capability_exception $e) {
909 $this->assertEquals('nopermissions', $e->errorcode);
910 }
911
912 // Sending for review.
913 $this->setUser($user);
914 api::plan_request_review($plan);
915 $plan->read();
916 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
917
918 // Sending for review by ID.
919 $plan->set_status(plan::STATUS_DRAFT);
920 $plan->update();
921 api::plan_request_review($plan->get_id());
922 $plan->read();
923 $this->assertEquals(plan::STATUS_WAITING_FOR_REVIEW, $plan->get_status());
924 }
925
926 /**
927 * Testing cancelling the review request.
928 */
929 public function test_plan_cancel_review_request() {
930 $data = $this->setup_workflow_data();
931 extract($data);
932
933 // Set waiting for review.
934 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
935 $tplplan->update();
936 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
937 $plan->update();
938
939 // Foreign user cannot do anything.
940 $this->setUser($otheruser);
941 try {
942 api::plan_cancel_review_request($plan);
943 $this->fail('The user can not read the plan.');
944 } catch (required_capability_exception $e) {
945 $this->assertEquals('nopermissions', $e->errorcode);
946 }
947
948 // Can not change a plan based on a template.
949 $this->setUser($user);
950 try {
951 api::plan_cancel_review_request($tplplan);
952 $this->fail('The plan is based on a template.');
953 } catch (coding_exception $e) {
954 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
955 }
956
957 // Can not cancel review request when not waiting for review.
958 $this->setUser($user);
959 $plan->set_status(plan::STATUS_DRAFT);
960 try {
961 api::plan_cancel_review_request($plan);
962 $this->fail('The plan cannot be sent for review at this stage.');
963 } catch (coding_exception $e) {
964 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
965 }
966
967 // Can not cancel review request when not waiting for review.
968 $this->setUser($user);
969 $plan->set_status(plan::STATUS_IN_REVIEW);
970 try {
971 api::plan_cancel_review_request($plan);
972 $this->fail('The plan review cannot be cancelled at this stage.');
973 } catch (coding_exception $e) {
974 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
975 }
976
977 // Can not cancel review request when not waiting for review.
978 $this->setUser($user);
979 $plan->set_status(plan::STATUS_ACTIVE);
980 try {
981 api::plan_cancel_review_request($plan);
982 $this->fail('The plan review cannot be cancelled at this stage.');
983 } catch (coding_exception $e) {
984 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
985 }
986
987 // Can not cancel review request when not waiting for review.
988 $this->setUser($user);
989 $plan->set_status(plan::STATUS_COMPLETE);
990 try {
991 api::plan_cancel_review_request($plan);
992 $this->fail('The plan review cannot be cancelled at this stage.');
993 } catch (coding_exception $e) {
994 $this->assertRegExp('/The plan review cannot be cancelled at this stage./', $e->getMessage());
995 }
996
997 // Cancelling as a reviewer.
998 $this->setUser($reviewer);
999 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1000 try {
1001 api::plan_cancel_review_request($plan);
1002 $this->fail('The user can not cancel a review request.');
1003 } catch (required_capability_exception $e) {
1004 $this->assertEquals('nopermissions', $e->errorcode);
1005 }
1006
1007 // Cancelling review request.
1008 $this->setUser($user);
1009 api::plan_cancel_review_request($plan);
1010 $plan->read();
1011 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1012
1013 // Cancelling review request by ID.
1014 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1015 $plan->update();
1016 api::plan_cancel_review_request($plan->get_id());
1017 $plan->read();
1018 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1019 }
1020
1021 /**
1022 * Testing starting the review.
1023 */
1024 public function test_plan_start_review() {
1025 $data = $this->setup_workflow_data();
1026 extract($data);
1027
1028 // Set waiting for review.
1029 $tplplan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1030 $tplplan->update();
1031 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1032 $plan->update();
1033
1034 // Foreign user cannot do anything.
1035 $this->setUser($otheruser);
1036 try {
1037 api::plan_start_review($plan);
1038 $this->fail('The user can not read the plan.');
1039 } catch (required_capability_exception $e) {
1040 $this->assertEquals('nopermissions', $e->errorcode);
1041 }
1042
1043 // Can not change a plan based on a template.
1044 $this->setUser($reviewer);
1045 try {
1046 api::plan_start_review($tplplan);
1047 $this->fail('The plan is based on a template.');
1048 } catch (coding_exception $e) {
1049 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1050 }
1051
1052 // Can not start a review when not waiting for review.
1053 $this->setUser($reviewer);
1054 $plan->set_status(plan::STATUS_DRAFT);
1055 try {
1056 api::plan_start_review($plan);
1057 $this->fail('The plan review cannot be started at this stage.');
1058 } catch (coding_exception $e) {
1059 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1060 }
1061
1062 // Can not start a review when not waiting for review.
1063 $this->setUser($reviewer);
1064 $plan->set_status(plan::STATUS_IN_REVIEW);
1065 try {
1066 api::plan_start_review($plan);
1067 $this->fail('The plan review cannot be started at this stage.');
1068 } catch (coding_exception $e) {
1069 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1070 }
1071
1072 // Can not start a review when not waiting for review.
1073 $this->setUser($reviewer);
1074 $plan->set_status(plan::STATUS_ACTIVE);
1075 try {
1076 api::plan_start_review($plan);
1077 $this->fail('The plan review cannot be started at this stage.');
1078 } catch (coding_exception $e) {
1079 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1080 }
1081
1082 // Can not start a review when not waiting for review.
1083 $this->setUser($reviewer);
1084 $plan->set_status(plan::STATUS_COMPLETE);
1085 try {
1086 api::plan_start_review($plan);
1087 $this->fail('The plan review cannot be started at this stage.');
1088 } catch (coding_exception $e) {
1089 $this->assertRegExp('/The plan review cannot be started at this stage./', $e->getMessage());
1090 }
1091
1092 // Starting as the owner.
1093 $this->setUser($user);
1094 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1095 try {
1096 api::plan_start_review($plan);
1097 $this->fail('The user can not start a review.');
1098 } catch (required_capability_exception $e) {
1099 $this->assertEquals('nopermissions', $e->errorcode);
1100 }
1101
1102 // Starting review.
1103 $this->setUser($reviewer);
1104 api::plan_start_review($plan);
1105 $plan->read();
1106 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1107 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1108
1109 // Starting review by ID.
1110 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1111 $plan->set_reviewerid(null);
1112 $plan->update();
1113 api::plan_start_review($plan->get_id());
1114 $plan->read();
1115 $this->assertEquals(plan::STATUS_IN_REVIEW, $plan->get_status());
1116 $this->assertEquals($reviewer->id, $plan->get_reviewerid());
1117 }
1118
1119 /**
1120 * Testing stopping the review.
1121 */
1122 public function test_plan_stop_review() {
1123 $data = $this->setup_workflow_data();
1124 extract($data);
1125
1126 // Set waiting for review.
1127 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1128 $tplplan->update();
1129 $plan->set_status(plan::STATUS_IN_REVIEW);
1130 $plan->update();
1131
1132 // Foreign user cannot do anything.
1133 $this->setUser($otheruser);
1134 try {
1135 api::plan_stop_review($plan);
1136 $this->fail('The user can not read the plan.');
1137 } catch (required_capability_exception $e) {
1138 $this->assertEquals('nopermissions', $e->errorcode);
1139 }
1140
1141 // Can not change a plan based on a template.
1142 $this->setUser($reviewer);
1143 try {
1144 api::plan_stop_review($tplplan);
1145 $this->fail('The plan is based on a template.');
1146 } catch (coding_exception $e) {
1147 $this->assertRegExp('/Template plans cannot be reviewed./', $e->getMessage());
1148 }
1149
1150 // Can not stop a review whe not in review.
1151 $this->setUser($reviewer);
1152 $plan->set_status(plan::STATUS_DRAFT);
1153 try {
1154 api::plan_stop_review($plan);
1155 $this->fail('The plan review cannot be stopped at this stage.');
1156 } catch (coding_exception $e) {
1157 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1158 }
1159
1160 // Can not stop a review whe not in review.
1161 $this->setUser($reviewer);
1162 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1163 try {
1164 api::plan_stop_review($plan);
1165 $this->fail('The plan review cannot be stopped at this stage.');
1166 } catch (coding_exception $e) {
1167 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1168 }
1169
1170 // Can not stop a review whe not in review.
1171 $this->setUser($reviewer);
1172 $plan->set_status(plan::STATUS_ACTIVE);
1173 try {
1174 api::plan_stop_review($plan);
1175 $this->fail('The plan review cannot be stopped at this stage.');
1176 } catch (coding_exception $e) {
1177 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1178 }
1179
1180 // Can not stop a review whe not in review.
1181 $this->setUser($reviewer);
1182 $plan->set_status(plan::STATUS_COMPLETE);
1183 try {
1184 api::plan_stop_review($plan);
1185 $this->fail('The plan review cannot be stopped at this stage.');
1186 } catch (coding_exception $e) {
1187 $this->assertRegExp('/The plan review cannot be stopped at this stage./', $e->getMessage());
1188 }
1189
1190 // Stopping as the owner.
1191 $this->setUser($user);
1192 $plan->set_status(plan::STATUS_IN_REVIEW);
1193 try {
1194 api::plan_stop_review($plan);
1195 $this->fail('The user can not stop a review.');
1196 } catch (required_capability_exception $e) {
1197 $this->assertEquals('nopermissions', $e->errorcode);
1198 }
1199
1200 // Stopping review.
1201 $this->setUser($reviewer);
1202 api::plan_stop_review($plan);
1203 $plan->read();
1204 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1205
1206 // Stopping review by ID.
1207 $plan->set_status(plan::STATUS_IN_REVIEW);
1208 $plan->update();
1209 api::plan_stop_review($plan->get_id());
1210 $plan->read();
1211 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1212 }
1213
1214 /**
1215 * Testing approving the plan.
1216 */
1217 public function test_approve_plan() {
1218 $data = $this->setup_workflow_data();
1219 extract($data);
1220
1221 // Set waiting for review.
1222 $tplplan->set_status(plan::STATUS_IN_REVIEW);
1223 $tplplan->update();
1224 $plan->set_status(plan::STATUS_IN_REVIEW);
1225 $plan->update();
1226
1227 // Foreign user cannot do anything.
1228 $this->setUser($otheruser);
1229 try {
1230 api::approve_plan($plan);
1231 $this->fail('The user can not read the plan.');
1232 } catch (required_capability_exception $e) {
1233 $this->assertEquals('nopermissions', $e->errorcode);
1234 }
1235
1236 // Can not change a plan based on a template.
1237 $this->setUser($reviewer);
1238 try {
1239 api::approve_plan($tplplan);
1240 $this->fail('The plan is based on a template.');
1241 } catch (coding_exception $e) {
1242 $this->assertRegExp('/Template plans are already approved./', $e->getMessage());
1243 }
1244
1245 // Can not approve a plan already approved.
1246 $this->setUser($reviewer);
1247 $plan->set_status(plan::STATUS_ACTIVE);
1248 try {
1249 api::approve_plan($plan);
1250 $this->fail('The plan cannot be approved at this stage.');
1251 } catch (coding_exception $e) {
1252 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1253 }
1254
1255 // Can not approve a plan already approved.
1256 $this->setUser($reviewer);
1257 $plan->set_status(plan::STATUS_COMPLETE);
1258 try {
1259 api::approve_plan($plan);
1260 $this->fail('The plan cannot be approved at this stage.');
1261 } catch (coding_exception $e) {
1262 $this->assertRegExp('/The plan cannot be approved at this stage./', $e->getMessage());
1263 }
1264
1265 // Approve as the owner.
1266 $this->setUser($user);
1267 $plan->set_status(plan::STATUS_IN_REVIEW);
1268 try {
1269 api::approve_plan($plan);
1270 $this->fail('The user can not approve the plan.');
1271 } catch (required_capability_exception $e) {
1272 $this->assertEquals('nopermissions', $e->errorcode);
1273 }
1274
1275 // Approve plan from in review.
1276 $this->setUser($reviewer);
1277 api::approve_plan($plan);
1278 $plan->read();
1279 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1280
1281 // Approve plan by ID.
1282 $plan->set_status(plan::STATUS_IN_REVIEW);
1283 $plan->update();
1284 api::approve_plan($plan->get_id());
1285 $plan->read();
1286 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1287
1288 // Approve plan from draft.
1289 $plan->set_status(plan::STATUS_DRAFT);
1290 $plan->update();
1291 api::approve_plan($plan);
1292 $plan->read();
1293 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1294
1295 // Approve plan from waiting for review.
1296 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1297 $plan->update();
1298 api::approve_plan($plan);
1299 $plan->read();
1300 $this->assertEquals(plan::STATUS_ACTIVE, $plan->get_status());
1301 }
1302
1303 /**
1304 * Testing stopping the review.
1305 */
1306 public function test_unapprove_plan() {
1307 $data = $this->setup_workflow_data();
1308 extract($data);
1309
1310 // Set waiting for review.
1311 $tplplan->set_status(plan::STATUS_ACTIVE);
1312 $tplplan->update();
1313 $plan->set_status(plan::STATUS_ACTIVE);
1314 $plan->update();
1315
1316 // Foreign user cannot do anything.
1317 $this->setUser($otheruser);
1318 try {
1319 api::unapprove_plan($plan);
1320 $this->fail('The user can not read the plan.');
1321 } catch (required_capability_exception $e) {
1322 $this->assertEquals('nopermissions', $e->errorcode);
1323 }
1324
1325 // Can not change a plan based on a template.
1326 $this->setUser($reviewer);
1327 try {
1328 api::unapprove_plan($tplplan);
1329 $this->fail('The plan is based on a template.');
1330 } catch (coding_exception $e) {
1331 $this->assertRegExp('/Template plans are always approved./', $e->getMessage());
1332 }
1333
1334 // Can not unapprove a non-draft plan.
1335 $this->setUser($reviewer);
1336 $plan->set_status(plan::STATUS_DRAFT);
1337 try {
1338 api::unapprove_plan($plan);
1339 $this->fail('The plan cannot be sent back to draft at this stage.');
1340 } catch (coding_exception $e) {
1341 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1342 }
1343
1344 // Can not unapprove a non-draft plan.
1345 $this->setUser($reviewer);
1346 $plan->set_status(plan::STATUS_WAITING_FOR_REVIEW);
1347 try {
1348 api::unapprove_plan($plan);
1349 $this->fail('The plan cannot be sent back to draft at this stage.');
1350 } catch (coding_exception $e) {
1351 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1352 }
1353
1354 // Can not unapprove a non-draft plan.
1355 $this->setUser($reviewer);
1356 $plan->set_status(plan::STATUS_IN_REVIEW);
1357 try {
1358 api::unapprove_plan($plan);
1359 $this->fail('The plan cannot be sent back to draft at this stage.');
1360 } catch (coding_exception $e) {
1361 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1362 }
1363
1364 // Can not unapprove a non-draft plan.
1365 $this->setUser($reviewer);
1366 $plan->set_status(plan::STATUS_COMPLETE);
1367 try {
1368 api::unapprove_plan($plan);
1369 $this->fail('The plan cannot be sent back to draft at this stage.');
1370 } catch (coding_exception $e) {
1371 $this->assertRegExp('/The plan cannot be sent back to draft at this stage./', $e->getMessage());
1372 }
1373
1374 // Unapprove as the owner.
1375 $this->setUser($user);
1376 $plan->set_status(plan::STATUS_ACTIVE);
1377 try {
1378 api::unapprove_plan($plan);
1379 $this->fail('The user can not unapprove the plan.');
1380 } catch (required_capability_exception $e) {
1381 $this->assertEquals('nopermissions', $e->errorcode);
1382 }
1383
1384 // Unapprove plan.
1385 $this->setUser($reviewer);
1386 api::unapprove_plan($plan);
1387 $plan->read();
1388 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1389
1390 // Unapprove plan by ID.
1391 $plan->set_status(plan::STATUS_ACTIVE);
1392 $plan->update();
1393 api::unapprove_plan($plan->get_id());
1394 $plan->read();
1395 $this->assertEquals(plan::STATUS_DRAFT, $plan->get_status());
1396 }
1397
192569ed
JPG
1398 /**
1399 * Test update plan and the managing of archived user competencies.
1400 */
1401 public function test_update_plan_manage_archived_competencies() {
1402 global $DB;
1403
1404 $this->resetAfterTest(true);
1405 $dg = $this->getDataGenerator();
1406 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1407
1408 $syscontext = context_system::instance();
1409
1410 // Create users and roles for the test.
1411 $user = $dg->create_user();
1412 $manageownrole = $dg->create_role(array(
1413 'name' => 'User manage own',
1414 'shortname' => 'manageown'
1415 ));
1416 assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1417 assign_capability('tool/lp:planviewowndraft', CAP_ALLOW, $manageownrole, $syscontext->id);
1418 assign_capability('tool/lp:planmanageown', CAP_ALLOW, $manageownrole, $syscontext->id);
1419 assign_capability('tool/lp:planviewown', CAP_ALLOW, $manageownrole, $syscontext->id);
1420 $dg->role_assign($manageownrole, $user->id, $syscontext->id);
1421 $this->setUser($user);
1422
1423 // Create a framework and assign competencies.
1424 $framework = $lpg->create_framework();
1425 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1426 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1427 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1428
1429 // Create two plans and assign competencies.
1430 $plan = $lpg->create_plan(array('userid' => $user->id));
1431 $otherplan = $lpg->create_plan(array('userid' => $user->id));
1432
1433 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c1->get_id()));
1434 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c2->get_id()));
1435 $lpg->create_plan_competency(array('planid' => $plan->get_id(), 'competencyid' => $c3->get_id()));
1436 $lpg->create_plan_competency(array('planid' => $otherplan->get_id(), 'competencyid' => $c1->get_id()));
1437
1438 $uclist = array(
1439 $lpg->create_user_competency(array(
1440 'userid' => $user->id,
1441 'competencyid' => $c1->get_id(),
1442 'proficiency' => true,
1443 'grade' => 1
1444 )),
1445 $lpg->create_user_competency(array(
1446 'userid' => $user->id,
1447 'competencyid' => $c2->get_id(),
1448 'proficiency' => false,
1449 'grade' => 2
1450 ))
1451 );
1452
1453 // Change status of the plan to complete.
1454 $record = $plan->to_record();
1455 $record->status = \tool_lp\plan::STATUS_COMPLETE;
1456
5bfab685
FM
1457 try {
1458 $plan = api::update_plan($record);
1459 $this->fail('We cannot complete a plan using api::update_plan().');
1460 } catch (coding_exception $e) {
1461 }
1462 api::complete_plan($plan);
192569ed
JPG
1463
1464 // Check that user compretencies are now in user_competency_plan objects and still in user_competency.
1465 $this->assertEquals(2, \tool_lp\user_competency::count_records());
1466 $this->assertEquals(3, \tool_lp\user_competency_plan::count_records());
1467
1468 $usercompetenciesplan = \tool_lp\user_competency_plan::get_records();
1469
1470 $this->assertEquals($uclist[0]->get_userid(), $usercompetenciesplan[0]->get_userid());
1471 $this->assertEquals($uclist[0]->get_competencyid(), $usercompetenciesplan[0]->get_competencyid());
1472 $this->assertEquals($uclist[0]->get_proficiency(), (bool) $usercompetenciesplan[0]->get_proficiency());
1473 $this->assertEquals($uclist[0]->get_grade(), $usercompetenciesplan[0]->get_grade());
1474 $this->assertEquals($plan->get_id(), $usercompetenciesplan[0]->get_planid());
1475
1476 $this->assertEquals($uclist[1]->get_userid(), $usercompetenciesplan[1]->get_userid());
1477 $this->assertEquals($uclist[1]->get_competencyid(), $usercompetenciesplan[1]->get_competencyid());
1478 $this->assertEquals($uclist[1]->get_proficiency(), (bool) $usercompetenciesplan[1]->get_proficiency());
1479 $this->assertEquals($uclist[1]->get_grade(), $usercompetenciesplan[1]->get_grade());
1480 $this->assertEquals($plan->get_id(), $usercompetenciesplan[1]->get_planid());
1481
1482 $this->assertEquals($user->id, $usercompetenciesplan[2]->get_userid());
1483 $this->assertEquals($c3->get_id(), $usercompetenciesplan[2]->get_competencyid());
1484 $this->assertNull($usercompetenciesplan[2]->get_proficiency());
1485 $this->assertNull($usercompetenciesplan[2]->get_grade());
1486 $this->assertEquals($plan->get_id(), $usercompetenciesplan[2]->get_planid());
1487
192569ed
JPG
1488 // Change status of the plan to active.
1489 $record = $plan->to_record();
1490 $record->status = \tool_lp\plan::STATUS_ACTIVE;
1491
d805cc37
IT
1492 try {
1493 api::update_plan($record);
1494 $this->fail('Completed plan can not be edited');
1495 } catch (coding_exception $e) {
1496 }
192569ed 1497
d805cc37 1498 api::reopen_plan($record->id);
192569ed
JPG
1499 // Check that user_competency_plan objects are deleted if the plan status is changed to another status.
1500 $this->assertEquals(2, \tool_lp\user_competency::count_records());
1501 $this->assertEquals(0, \tool_lp\user_competency_plan::count_records());
1502 }
1503
1504 /**
1505 * Test remove plan and the managing of archived user competencies.
1506 */
1507 public function test_delete_plan_manage_archived_competencies() {
1508 $this->resetAfterTest(true);
1509 $dg = $this->getDataGenerator();
1510 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1511
1512 $syscontext = context_system::instance();
1513
1514 // Create user and role for the test.
1515 $user = $dg->create_user();
1516 $managerole = $dg->create_role(array(
1517 'name' => 'User manage own',
1518 'shortname' => 'manageown'
1519 ));
1520 assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $managerole, $syscontext->id);
1521 assign_capability('tool/lp:planmanageown', CAP_ALLOW, $managerole, $syscontext->id);
1522 $dg->role_assign($managerole, $user->id, $syscontext->id);
1523 $this->setUser($user);
1524
1525 // Create a framework and assign competencies.
1526 $framework = $lpg->create_framework();
1527 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1528 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1529 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1530
1531 // Create completed plan with records in user_competency.
1532 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \tool_lp\plan::STATUS_COMPLETE));
1533
1534 $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c1->get_id()));
1535 $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c2->get_id()));
1536
1537 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
1538 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id()));
1539
1540 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
1541 'planid' => $completedplan->get_id()));
1542 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
1543 'planid' => $completedplan->get_id()));
1544
1545 api::delete_plan($completedplan->get_id());
1546
1547 // Check that achived user competencies are deleted.
1548 $this->assertEquals(0, \tool_lp\plan::count_records());
1549 $this->assertEquals(2, \tool_lp\user_competency::count_records());
1550 $this->assertEquals(0, \tool_lp\user_competency_plan::count_records());
1551 }
1552
1553 /**
1554 * Test listing of plan competencies.
1555 */
1556 public function test_list_plan_competencies_manage_archived_competencies() {
1557 $this->resetAfterTest(true);
1558 $dg = $this->getDataGenerator();
1559 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1560
1561 $syscontext = context_system::instance();
1562
1563 // Create user and role for the test.
1564 $user = $dg->create_user();
1565 $viewrole = $dg->create_role(array(
1566 'name' => 'User view',
1567 'shortname' => 'view'
1568 ));
1569 assign_capability('tool/lp:planviewdraft', CAP_ALLOW, $viewrole, $syscontext->id);
1570 assign_capability('tool/lp:planview', CAP_ALLOW, $viewrole, $syscontext->id);
1571 $dg->role_assign($viewrole, $user->id, $syscontext->id);
1572 $this->setUser($user);
1573
1574 // Create a framework and assign competencies.
1575 $framework = $lpg->create_framework();
1576 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1577 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1578 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
1579
1580 // Create draft plan with records in user_competency.
1581 $draftplan = $lpg->create_plan(array('userid' => $user->id));
1582
1583 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c1->get_id()));
1584 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c2->get_id()));
1585 $lpg->create_plan_competency(array('planid' => $draftplan->get_id(), 'competencyid' => $c3->get_id()));
1586
1587 $uc1 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
1588 $uc2 = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c2->get_id()));
1589
1590 // Check that user_competency objects are returned when plan status is not complete.
1591 $plancompetencies = api::list_plan_competencies($draftplan);
1592
1593 $this->assertCount(3, $plancompetencies);
1594 $this->assertInstanceOf('\tool_lp\user_competency', $plancompetencies[0]->usercompetency);
1595 $this->assertEquals($uc1->get_id(), $plancompetencies[0]->usercompetency->get_id());
1596 $this->assertNull($plancompetencies[0]->usercompetencyplan);
1597
1598 $this->assertInstanceOf('\tool_lp\user_competency', $plancompetencies[1]->usercompetency);
1599 $this->assertEquals($uc2->get_id(), $plancompetencies[1]->usercompetency->get_id());
1600 $this->assertNull($plancompetencies[1]->usercompetencyplan);
1601
1602 $this->assertInstanceOf('\tool_lp\user_competency', $plancompetencies[2]->usercompetency);
1603 $this->assertEquals(0, $plancompetencies[2]->usercompetency->get_id());
1604 $this->assertNull($plancompetencies[2]->usercompetencyplan);
1605
1606 // Create completed plan with records in user_competency_plan.
1607 $completedplan = $lpg->create_plan(array('userid' => $user->id, 'status' => \tool_lp\plan::STATUS_COMPLETE));
1608
1609 $pc1 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c1->get_id()));
1610 $pc2 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c2->get_id()));
1611 $pc3 = $lpg->create_plan_competency(array('planid' => $completedplan->get_id(), 'competencyid' => $c3->get_id()));
1612
1613 $ucp1 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c1->get_id(),
1614 'planid' => $completedplan->get_id()));
1615 $ucp2 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c2->get_id(),
1616 'planid' => $completedplan->get_id()));
192569ed
JPG
1617 $ucp3 = $lpg->create_user_competency_plan(array('userid' => $user->id, 'competencyid' => $c3->get_id(),
1618 'planid' => $completedplan->get_id()));
1619
1620 // Check that user_competency_plan objects are returned when plan status is complete.
1621 $plancompetencies = api::list_plan_competencies($completedplan);
1622
1623 $this->assertCount(3, $plancompetencies);
1624 $this->assertInstanceOf('\tool_lp\user_competency_plan', $plancompetencies[0]->usercompetencyplan);
1625 $this->assertEquals($ucp1->get_id(), $plancompetencies[0]->usercompetencyplan->get_id());
1626 $this->assertNull($plancompetencies[0]->usercompetency);
1627 $this->assertInstanceOf('\tool_lp\user_competency_plan', $plancompetencies[1]->usercompetencyplan);
1628 $this->assertEquals($ucp2->get_id(), $plancompetencies[1]->usercompetencyplan->get_id());
1629 $this->assertNull($plancompetencies[1]->usercompetency);
1630 $this->assertInstanceOf('\tool_lp\user_competency_plan', $plancompetencies[2]->usercompetencyplan);
1631 $this->assertEquals($ucp3->get_id(), $plancompetencies[2]->usercompetencyplan->get_id());
1632 $this->assertNull($plancompetencies[2]->usercompetency);
1633 }
1634
bee480a4
FM
1635 public function test_create_template_cohort() {
1636 $this->resetAfterTest(true);
1637 $this->setAdminUser();
1638
1639 $dg = $this->getDataGenerator();
1640 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1641
1642 $c1 = $dg->create_cohort();
1643 $c2 = $dg->create_cohort();
1644 $t1 = $lpg->create_template();
1645 $t2 = $lpg->create_template();
1646
1647 $this->assertEquals(0, \tool_lp\template_cohort::count_records());
1648
1649 // Create two relations with mixed parameters.
1650 $result = api::create_template_cohort($t1->get_id(), $c1->id);
1651 $result = api::create_template_cohort($t1, $c2);
1652
1653 $this->assertEquals(2, \tool_lp\template_cohort::count_records());
1654 $this->assertInstanceOf('tool_lp\template_cohort', $result);
1655 $this->assertEquals($c2->id, $result->get_cohortid());
1656 $this->assertEquals($t1->get_id(), $result->get_templateid());
1657 $this->assertEquals(2, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1658 $this->assertEquals(0, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1659 }
1660
5a4ee001
IT
1661 public function test_delete_template() {
1662 $this->resetAfterTest(true);
1663 $this->setAdminUser();
1664
1665 $dg = $this->getDataGenerator();
1666 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1667
1668 $c1 = $dg->create_cohort();
1669 $c2 = $dg->create_cohort();
1670 $template = $lpg->create_template();
1671 $id = $template->get_id();
1672
1673 // Create 2 template cohorts.
1674 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get_id(), 'cohortid' => $c1->id));
1675 $tc1 = $lpg->create_template_cohort(array('templateid' => $template->get_id(), 'cohortid' => $c2->id));
1676
1677 // Check pre-test.
1678 $this->assertTrue(tool_lp\template::record_exists($id));
1679 $this->assertEquals(2, \tool_lp\template_cohort::count_records(array('templateid' => $id)));
1680
1681 $result = api::delete_template($template->get_id());
1682 $this->assertTrue($result);
1683
1684 // Check that the template deos not exist anymore.
1685 $this->assertFalse(tool_lp\template::record_exists($id));
1686
1687 // Test if associated cohorts are also deleted.
1688 $this->assertEquals(0, \tool_lp\template_cohort::count_records(array('templateid' => $id)));
1689 }
1690
bee480a4
FM
1691 public function test_delete_template_cohort() {
1692 $this->resetAfterTest(true);
1693 $this->setAdminUser();
1694
1695 $dg = $this->getDataGenerator();
1696 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
1697
1698 $c1 = $dg->create_cohort();
1699 $c2 = $dg->create_cohort();
1700 $t1 = $lpg->create_template();
1701 $t2 = $lpg->create_template();
1702 $tc1 = $lpg->create_template_cohort(array('templateid' => $t1->get_id(), 'cohortid' => $c1->id));
1703 $tc1 = $lpg->create_template_cohort(array('templateid' => $t2->get_id(), 'cohortid' => $c2->id));
1704
1705 $this->assertEquals(2, \tool_lp\template_cohort::count_records());
1706 $this->assertEquals(1, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1707 $this->assertEquals(1, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1708
1709 // Delete existing.
1710 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1711 $this->assertTrue($result);
1712 $this->assertEquals(1, \tool_lp\template_cohort::count_records());
1713 $this->assertEquals(0, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1714 $this->assertEquals(1, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1715
1716 // Delete non-existant.
1717 $result = api::delete_template_cohort($t1->get_id(), $c1->id);
1718 $this->assertTrue($result);
1719 $this->assertEquals(1, \tool_lp\template_cohort::count_records());
1720 $this->assertEquals(0, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t1->get_id())));
1721 $this->assertEquals(1, \tool_lp\template_cohort::count_records_select('templateid = :id', array('id' => $t2->get_id())));
1722 }
4c0e8167 1723
914b580e
FM
1724 public function test_add_evidence_log() {
1725 $this->resetAfterTest(true);
1726 $dg = $this->getDataGenerator();
1727 $lpg = $dg->get_plugin_generator('tool_lp');
1728
1729 $u1 = $dg->create_user();
1730 $u1ctx = context_user::instance($u1->id);
1731 $f1 = $lpg->create_framework();
1732 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1733 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1734
1735 // Creating a standard evidence with minimal information.
1736 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata', 'error');
1737 $evidence->read();
1738 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1739 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1740 $this->assertSame(null, $uc->get_grade());
1741 $this->assertSame(null, $uc->get_proficiency());
1742 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1743 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1744 $this->assertEquals(\tool_lp\evidence::ACTION_LOG, $evidence->get_action());
1745 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1746 $this->assertEquals('error', $evidence->get_desccomponent());
1747 $this->assertSame(null, $evidence->get_desca());
1748 $this->assertSame(null, $evidence->get_url());
1749 $this->assertSame(null, $evidence->get_grade());
1750 $this->assertSame(null, $evidence->get_actionuserid());
1751
1752 // Creating a standard evidence with more information.
1753 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata', 'error',
1754 '$a', false, 'http://moodle.org', null, 2);
1755 $evidence->read();
1756 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1757 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1758 $this->assertSame(null, $uc->get_grade());
1759 $this->assertSame(null, $uc->get_proficiency());
1760 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1761 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1762 $this->assertEquals(\tool_lp\evidence::ACTION_LOG, $evidence->get_action());
1763 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1764 $this->assertEquals('error', $evidence->get_desccomponent());
1765 $this->assertEquals('$a', $evidence->get_desca());
1766 $this->assertEquals('http://moodle.org', $evidence->get_url());
1767 $this->assertSame(null, $evidence->get_grade());
1768 $this->assertEquals(2, $evidence->get_actionuserid());
1769
1770 // Creating a standard evidence and send for review.
1771 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata',
1772 'error', null, true);
1773 $evidence->read();
1774 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
1775 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
1776
1777 // Trying to pass a grade should fail.
1778 try {
1779 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata', 'error',
1780 null, false, null, 1);
1781 $this->fail('A grade can not be set');
1782 } catch (coding_exception $e) {
1783 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
1784 }
1785 }
1786
1787 public function test_add_evidence_suggest() {
1788 $this->resetAfterTest(true);
1789 $dg = $this->getDataGenerator();
1790 $lpg = $dg->get_plugin_generator('tool_lp');
1791
1792 $u1 = $dg->create_user();
1793 $u1ctx = context_user::instance($u1->id);
1794 $f1 = $lpg->create_framework();
1795 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1796 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1797
1798 // Creating an evidence with minimal information.
1799 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_SUGGEST, 'invaliddata',
1800 'error', null, false, null, 1, 2);
1801 $evidence->read();
1802 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1803 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1804 $this->assertSame(null, $uc->get_grade()); // We don't grade, we just suggest.
1805 $this->assertSame(null, $uc->get_proficiency());
1806 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1807 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1808 $this->assertEquals(\tool_lp\evidence::ACTION_SUGGEST, $evidence->get_action());
1809 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1810 $this->assertEquals('error', $evidence->get_desccomponent());
1811 $this->assertSame(null, $evidence->get_desca());
1812 $this->assertSame(null, $evidence->get_url());
1813 $this->assertEquals(1, $evidence->get_grade());
1814 $this->assertEquals(2, $evidence->get_actionuserid());
1815
1816 // Creating a standard evidence and send for review.
1817 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_SUGGEST, 'invaliddata',
1818 'error', null, true, null, 1, 2);
1819 $evidence->read();
1820 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
1821 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
1822
1823 // Trying not to pass a grade should fail.
1824 try {
1825 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_SUGGEST, 'invaliddata', 'error',
1826 false, null);
1827 $this->fail('A grade must be set');
1828 } catch (coding_exception $e) {
1829 $this->assertRegExp('/grade MUST be set/', $e->getMessage());
1830 }
1831 }
1832
1833 public function test_add_evidence_complete() {
1834 $this->resetAfterTest(true);
1835 $dg = $this->getDataGenerator();
1836 $lpg = $dg->get_plugin_generator('tool_lp');
1837
1838 $u1 = $dg->create_user();
1839 $u1ctx = context_user::instance($u1->id);
1840 $scale = $dg->create_scale(array('scale' => 'A,B,C,D'));
1841 $scaleconfig = array(array('scaleid' => $scale->id));
1842 $scaleconfig[] = array('name' => 'A', 'id' => 1, 'scaledefault' => 0, 'proficient' => 0);
1843 $scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 1, 'proficient' => 0);
1844 $scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 1);
1845 $scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 0, 'proficient' => 1);
1846 $c2scaleconfig = array(array('scaleid' => $scale->id));
1847 $c2scaleconfig[] = array('name' => 'A', 'id' => 1, 'scaledefault' => 0, 'proficient' => 0);
1848 $c2scaleconfig[] = array('name' => 'B', 'id' => 2, 'scaledefault' => 0, 'proficient' => 1);
1849 $c2scaleconfig[] = array('name' => 'C', 'id' => 3, 'scaledefault' => 0, 'proficient' => 0);
1850 $c2scaleconfig[] = array('name' => 'D', 'id' => 4, 'scaledefault' => 1, 'proficient' => 1);
1851 $f1 = $lpg->create_framework(array('scaleid' => $scale->id, 'scaleconfiguration' => $scaleconfig));
1852 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1853 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'scaleid' => $scale->id,
1854 'scaleconfiguration' => $c2scaleconfig));
1855 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1856
1857 // Creating an evidence with minimal information.
1858 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_COMPLETE, 'invaliddata',
1859 'error');
1860 $evidence->read();
1861 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1862 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1863 $this->assertEquals(2, $uc->get_grade()); // The grade has been set automatically to the framework default.
1864 $this->assertEquals(0, $uc->get_proficiency());
1865 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1866 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1867 $this->assertEquals(\tool_lp\evidence::ACTION_COMPLETE, $evidence->get_action());
1868 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1869 $this->assertEquals('error', $evidence->get_desccomponent());
1870 $this->assertSame(null, $evidence->get_desca());
1871 $this->assertSame(null, $evidence->get_url());
1872 $this->assertEquals(2, $evidence->get_grade());
1873 $this->assertSame(null, $evidence->get_actionuserid());
1874
1875 // Creating an evidence complete on competency with custom scale.
1876 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_COMPLETE, 'invaliddata',
1877 'error');
1878 $evidence->read();
1879 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
1880 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1881 $this->assertEquals(4, $uc->get_grade()); // The grade has been set automatically to the competency default.
1882 $this->assertEquals(true, $uc->get_proficiency());
1883 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1884 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1885 $this->assertEquals(\tool_lp\evidence::ACTION_COMPLETE, $evidence->get_action());
1886 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1887 $this->assertEquals('error', $evidence->get_desccomponent());
1888 $this->assertSame(null, $evidence->get_desca());
1889 $this->assertSame(null, $evidence->get_url());
1890 $this->assertEquals(4, $evidence->get_grade());
1891 $this->assertSame(null, $evidence->get_actionuserid());
1892
1893 // Creating an evidence complete on a user competency with an existing grade.
1894 $uc = $lpg->create_user_competency(array('userid' => $u1->id, 'competencyid' => $c3->get_id(), 'grade' => 1,
1895 'proficiency' => 0));
1896 $this->assertEquals(1, $uc->get_grade());
1897 $this->assertEquals(0, $uc->get_proficiency());
1898 $evidence = api::add_evidence($u1->id, $c3->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_COMPLETE, 'invaliddata',
1899 'error');
1900 $evidence->read();
1901 $uc->read();
1902 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1903 $this->assertEquals(1, $uc->get_grade()); // The grade has not been changed.
1904 $this->assertEquals(0, $uc->get_proficiency());
1905 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1906 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1907 $this->assertEquals(\tool_lp\evidence::ACTION_COMPLETE, $evidence->get_action());
1908 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1909 $this->assertEquals('error', $evidence->get_desccomponent());
1910 $this->assertSame(null, $evidence->get_desca());
1911 $this->assertSame(null, $evidence->get_url());
1912 $this->assertEquals(2, $evidence->get_grade()); // The complete grade has been set.
1913 $this->assertSame(null, $evidence->get_actionuserid());
1914
1915 // Creating a standard evidence and send for review.
1916 $evidence = api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_COMPLETE, 'invaliddata',
1917 'error', null, true);
1918 $evidence->read();
1919 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
1920 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
1921
1922 // Trying to pass a grade should throw an exception.
1923 try {
1924 api::add_evidence($u1->id, $c2->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_COMPLETE, 'invaliddata',
1925 'error', null, false, null, 1);
1926 } catch (coding_exception $e) {
1927 $this->assertRegExp('/grade MUST NOT be set/', $e->getMessage());
1928 }
1929 }
1930
1931 public function test_add_evidence_override() {
1932 $this->resetAfterTest(true);
1933 $dg = $this->getDataGenerator();
1934 $lpg = $dg->get_plugin_generator('tool_lp');
1935
1936 $u1 = $dg->create_user();
1937 $u1ctx = context_user::instance($u1->id);
1938 $f1 = $lpg->create_framework();
1939 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
1940
1941 // Creating an evidence with minimal information.
1942 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_OVERRIDE, 'invaliddata',
1943 'error');
1944 $evidence->read();
1945 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1946 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1947 $this->assertSame(null, $uc->get_grade()); // We overrode with 'null'.
1948 $this->assertSame(null, $uc->get_proficiency());
1949 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1950 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1951 $this->assertEquals(\tool_lp\evidence::ACTION_OVERRIDE, $evidence->get_action());
1952 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1953 $this->assertEquals('error', $evidence->get_desccomponent());
1954 $this->assertSame(null, $evidence->get_desca());
1955 $this->assertSame(null, $evidence->get_url());
1956 $this->assertSame(null, $evidence->get_grade()); // We overrode with 'null'.
1957 $this->assertSame(null, $evidence->get_actionuserid());
1958
1959 // Creating an evidence with a grade information.
1960 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_OVERRIDE, 'invaliddata',
1961 'error', null, false, null, 3);
1962 $evidence->read();
1963 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1964 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1965 $this->assertEquals(3, $uc->get_grade());
1966 $this->assertEquals(true, $uc->get_proficiency());
1967 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1968 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1969 $this->assertEquals(\tool_lp\evidence::ACTION_OVERRIDE, $evidence->get_action());
1970 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1971 $this->assertEquals('error', $evidence->get_desccomponent());
1972 $this->assertSame(null, $evidence->get_desca());
1973 $this->assertSame(null, $evidence->get_url());
1974 $this->assertEquals(3, $evidence->get_grade());
1975 $this->assertSame(null, $evidence->get_actionuserid());
1976
1977 // Creating an evidence with another grade information.
1978 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_OVERRIDE, 'invaliddata',
1979 'error', null, false, null, 1);
1980 $evidence->read();
1981 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
1982 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc->get_status());
1983 $this->assertEquals(1, $uc->get_grade());
1984 $this->assertEquals(0, $uc->get_proficiency());
1985 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
1986 $this->assertEquals($u1ctx->id, $evidence->get_contextid());
1987 $this->assertEquals(\tool_lp\evidence::ACTION_OVERRIDE, $evidence->get_action());
1988 $this->assertEquals('invaliddata', $evidence->get_descidentifier());
1989 $this->assertEquals('error', $evidence->get_desccomponent());
1990 $this->assertSame(null, $evidence->get_desca());
1991 $this->assertSame(null, $evidence->get_url());
1992 $this->assertEquals(1, $evidence->get_grade());
1993 $this->assertSame(null, $evidence->get_actionuserid());
1994
1995 // Creating reverting the grade and send for review.
1996 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_OVERRIDE, 'invaliddata',
1997 'error', null, true);
1998 $evidence->read();
1999 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2000 $this->assertSame(null, $uc->get_grade());
2001 $this->assertSame(null, $uc->get_proficiency());
2002 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2003 $this->assertSame(null, $evidence->get_grade());
2004 }
2005
2006 public function test_add_evidence_and_send_for_review() {
2007 $this->resetAfterTest(true);
2008 $dg = $this->getDataGenerator();
2009 $lpg = $dg->get_plugin_generator('tool_lp');
2010
2011 $u1 = $dg->create_user();
2012 $u1ctx = context_user::instance($u1->id);
2013 $f1 = $lpg->create_framework();
2014 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2015
2016 // Non-existing user competencies are created up for review.
2017 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata',
2018 'error', null, true);
2019 $uc = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2020 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2021
2022 // Existing user competencies sent for review don't change.
2023 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata',
2024 'error', null, true);
2025 $uc->read();
2026 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc->get_status());
2027
2028 // A user competency with a status non-idle won't change.
2029 $uc->set_status(\tool_lp\user_competency::STATUS_IN_REVIEW);
2030 $uc->update();
2031 $evidence = api::add_evidence($u1->id, $c1->get_id(), $u1ctx->id, \tool_lp\evidence::ACTION_LOG, 'invaliddata',
2032 'error', null, true);
2033 $uc->read();
2034 $this->assertEquals(\tool_lp\user_competency::STATUS_IN_REVIEW, $uc->get_status());
2035 }
2036
4c0e8167
SG
2037 /**
2038 * Test add evidence for existing user_competency.
2039 */
2040 public function test_add_evidence_existing_user_competency() {
2041 $this->resetAfterTest(true);
2042 $dg = $this->getDataGenerator();
2043 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2044
2045 $syscontext = context_system::instance();
2046
2047 // Create users.
2048 $user = $dg->create_user();
2049 $this->setUser($user);
2050
2051 // Create a framework and assign competencies.
2052 $framework = $lpg->create_framework();
2053 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2054 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2055 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2056 $uc = $lpg->create_user_competency(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
914b580e
FM
2057 $this->assertSame(null, $uc->get_grade());
2058 $this->assertSame(null, $uc->get_proficiency());
4c0e8167
SG
2059
2060 // Create an evidence and check it was created with the right usercomptencyid and information.
914b580e
FM
2061 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \tool_lp\evidence::ACTION_OVERRIDE,
2062 'invalidevidencedesc', 'tool_lp', array('a' => 'b'), false, 'http://moodle.org', 1, 2);
4c0e8167
SG
2063 $this->assertEquals(1, \tool_lp\evidence::count_records());
2064
2065 $evidence->read();
914b580e 2066 $uc->read();
4c0e8167
SG
2067 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2068 $this->assertEquals('invalidevidencedesc', $evidence->get_descidentifier());
2069 $this->assertEquals('tool_lp', $evidence->get_desccomponent());
2070 $this->assertEquals((object) array('a' => 'b'), $evidence->get_desca());
914b580e
FM
2071 $this->assertEquals('http://moodle.org', $evidence->get_url());
2072 $this->assertEquals(\tool_lp\evidence::ACTION_OVERRIDE, $evidence->get_action());
2073 $this->assertEquals(2, $evidence->get_actionuserid());
4c0e8167 2074 $this->assertEquals(1, $evidence->get_grade());
914b580e
FM
2075 $this->assertEquals(1, $uc->get_grade());
2076 $this->assertEquals(0, $uc->get_proficiency());
4c0e8167
SG
2077 }
2078
2079 /**
914b580e 2080 * Test add evidence for non-existing user_competency.
4c0e8167
SG
2081 */
2082 public function test_add_evidence_no_existing_user_competency() {
2083 $this->resetAfterTest(true);
2084 $dg = $this->getDataGenerator();
2085 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2086
2087 $syscontext = context_system::instance();
2088
2089 // Create users.
2090 $user = $dg->create_user();
2091 $this->setUser($user);
2092
2093 // Create a framework and assign competencies.
2094 $framework = $lpg->create_framework();
2095 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2096 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
914b580e 2097 $this->assertEquals(0, \tool_lp\user_competency::count_records());
4c0e8167 2098
914b580e
FM
2099 // Create an evidence without a user competency record.
2100 $evidence = api::add_evidence($user->id, $c1->get_id(), $syscontext->id, \tool_lp\evidence::ACTION_OVERRIDE,
2101 'invalidevidencedesc', 'tool_lp', 'Hello world!', false, 'http://moodle.org', 1, 2);
4c0e8167 2102 $this->assertEquals(1, \tool_lp\evidence::count_records());
914b580e 2103 $this->assertEquals(1, \tool_lp\user_competency::count_records());
4c0e8167 2104
914b580e
FM
2105 $uc = \tool_lp\user_competency::get_record(array('userid' => $user->id, 'competencyid' => $c1->get_id()));
2106 $evidence->read();
2107 $this->assertEquals($uc->get_id(), $evidence->get_usercompetencyid());
2108 $this->assertEquals('invalidevidencedesc', $evidence->get_descidentifier());
2109 $this->assertEquals('tool_lp', $evidence->get_desccomponent());
2110 $this->assertEquals('Hello world!', $evidence->get_desca());
2111 $this->assertEquals('http://moodle.org', $evidence->get_url());
2112 $this->assertEquals(\tool_lp\evidence::ACTION_OVERRIDE, $evidence->get_action());
2113 $this->assertEquals(2, $evidence->get_actionuserid());
2114 $this->assertEquals(1, $evidence->get_grade());
2115 $this->assertEquals(1, $uc->get_grade());
2116 $this->assertEquals(0, $uc->get_proficiency());
2117 }
2118
9373acf6
FM
2119 public function test_add_evidence_applies_competency_rules() {
2120 $this->resetAfterTest(true);
2121 $dg = $this->getDataGenerator();
2122 $lpg = $dg->get_plugin_generator('tool_lp');
2123 $syscontext = context_system::instance();
2124 $ctxid = $syscontext->id;
2125
2126 $u1 = $dg->create_user();
2127
2128 // Setting up the framework.
2129 $f1 = $lpg->create_framework();
2130 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2131 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2132 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2133 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2134 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c2->get_id()));
2135 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2136 $c3a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c3->get_id()));
2137 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2138 $c4a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c4->get_id()));
2139 $c5 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2140
2141 // Setting up the rules.
2142 $c1->set_ruletype('tool_lp\\competency_rule_all');
2143 $c1->set_ruleoutcome(\tool_lp\competency::OUTCOME_COMPLETE);
2144 $c1->update();
2145 $c2->set_ruletype('tool_lp\\competency_rule_all');
2146 $c2->set_ruleoutcome(\tool_lp\competency::OUTCOME_RECOMMEND);
2147 $c2->update();
2148 $c3->set_ruletype('tool_lp\\competency_rule_all');
2149 $c3->set_ruleoutcome(\tool_lp\competency::OUTCOME_EVIDENCE);
2150 $c3->update();
2151 $c4->set_ruletype('tool_lp\\competency_rule_all');
2152 $c4->set_ruleoutcome(\tool_lp\competency::OUTCOME_NONE);
2153 $c4->update();
2154
2155 // Confirm the current data.
2156 $this->assertEquals(0, user_competency::count_records());
2157 $this->assertEquals(0, evidence::count_records());
2158
2159 // Let's do this!
2160 // First let's confirm that evidence not marking a completion have no impact.
2161 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_LOG, 'commentincontext', 'core');
2162 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get_id()));
2163 $this->assertSame(null, $uc1a->get_proficiency());
2164 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c1->get_id())));
2165
2166 api::add_evidence($u1->id, $c2a, $ctxid, evidence::ACTION_SUGGEST, 'commentincontext', 'core', null, false, null, 1);
2167 $uc2a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2a->get_id()));
2168 $this->assertSame(null, $uc2a->get_proficiency());
2169 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c2->get_id())));
2170
2171 // Now let's try complete a competency but the rule won't match (not all children are complete).
2172 // The parent (the thing with the rule) will be created but won't have any evidence attached, and not
2173 // not be marked as completed.
2174 api::add_evidence($u1->id, $c1a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2175 $uc1a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1a->get_id()));
2176 $this->assertEquals(true, $uc1a->get_proficiency());
2177 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2178 $this->assertSame(null, $uc1->get_proficiency());
2179 $this->assertEquals(0, evidence::count_records(array('usercompetencyid' => $uc1->get_id())));
2180
2181 // Now we complete the other child. That will mark the parent as complete with an evidence.
2182 api::add_evidence($u1->id, $c1b, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2183 $uc1b = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1b->get_id()));
2184 $this->assertEquals(true, $uc1a->get_proficiency());
2185 $uc1 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c1->get_id()));
2186 $this->assertEquals(true, $uc1->get_proficiency());
2187 $this->assertEquals(user_competency::STATUS_IDLE, $uc1->get_status());
2188 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc1->get_id())));
2189
2190 // Check rule recommending.
2191 api::add_evidence($u1->id, $c2a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2192 $uc2a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2a->get_id()));
2193 $this->assertEquals(true, $uc1a->get_proficiency());
2194 $uc2 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2195 $this->assertSame(null, $uc2->get_proficiency());
2196 $this->assertEquals(user_competency::STATUS_WAITING_FOR_REVIEW, $uc2->get_status());
2197 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc2->get_id())));
2198
2199 // Check rule evidence.
2200 api::add_evidence($u1->id, $c3a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2201 $uc3a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3a->get_id()));
2202 $this->assertEquals(true, $uc1a->get_proficiency());
2203 $uc3 = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get_id()));
2204 $this->assertSame(null, $uc3->get_proficiency());
2205 $this->assertEquals(user_competency::STATUS_IDLE, $uc3->get_status());
2206 $this->assertEquals(1, evidence::count_records(array('usercompetencyid' => $uc3->get_id())));
2207
2208 // Check rule nothing.
2209 api::add_evidence($u1->id, $c4a, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2210 $uc4a = user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4a->get_id()));
2211 $this->assertEquals(true, $uc1a->get_proficiency());
2212 $this->assertFalse(user_competency::record_exists_select('userid = ? AND competencyid = ?', array($u1->id, $c4->get_id())));
2213
2214 // Check marking on something that has no parent. This just checks that nothing breaks.
2215 api::add_evidence($u1->id, $c5, $ctxid, evidence::ACTION_COMPLETE, 'commentincontext', 'core');
2216 }
2217
914b580e
FM
2218 public function test_observe_course_completed() {
2219 $this->resetAfterTest(true);
2220 $dg = $this->getDataGenerator();
2221 $lpg = $dg->get_plugin_generator('tool_lp');
2222
2223 // Set-up users, framework, competencies and course competencies.
2224 $course = $dg->create_course();
2225 $coursectx = context_course::instance($course->id);
2226 $u1 = $dg->create_user();
2227 $f1 = $lpg->create_framework();
2228 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2229 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2230 $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2231 $c4 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2232 $cc1 = $lpg->create_course_competency(array('competencyid' => $c1->get_id(), 'courseid' => $course->id,
2233 'ruleoutcome' => \tool_lp\course_competency::OUTCOME_NONE));
2234 $cc2 = $lpg->create_course_competency(array('competencyid' => $c2->get_id(), 'courseid' => $course->id,
2235 'ruleoutcome' => \tool_lp\course_competency::OUTCOME_EVIDENCE));
2236 $cc3 = $lpg->create_course_competency(array('competencyid' => $c3->get_id(), 'courseid' => $course->id,
2237 'ruleoutcome' => \tool_lp\course_competency::OUTCOME_RECOMMEND));
2238 $cc4 = $lpg->create_course_competency(array('competencyid' => $c4->get_id(), 'courseid' => $course->id,
2239 'ruleoutcome' => \tool_lp\course_competency::OUTCOME_COMPLETE));
2240
2241 $event = \core\event\course_completed::create(array(
2242 'objectid' => 1,
2243 'relateduserid' => $u1->id,
2244 'context' => $coursectx,
2245 'courseid' => $course->id,
2246 'other' => array('relateduserid' => $u1->id)
2247 ));
2248 $this->assertEquals(0, \tool_lp\user_competency::count_records());
2249 $this->assertEquals(0, \tool_lp\evidence::count_records());
2250
2251 // Let's go!
2252 api::observe_course_completed($event);
2253 $this->assertEquals(3, \tool_lp\user_competency::count_records());
2254 $this->assertEquals(3, \tool_lp\evidence::count_records());
2255
2256 // Outcome NONE did nothing.
2257 $this->assertFalse(\tool_lp\user_competency::record_exists_select('userid = :uid AND competencyid = :cid', array(
2258 'uid' => $u1->id, 'cid' => $c1->get_id()
2259 )));
2260
2261 // Outcome evidence.
2262 $uc2 = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c2->get_id()));
2263 $ev2 = \tool_lp\evidence::get_record(array('usercompetencyid' => $uc2->get_id()));
2264
2265 $this->assertEquals(null, $uc2->get_grade());
2266 $this->assertEquals(null, $uc2->get_proficiency());
2267 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc2->get_status());
2268
2269 $this->assertEquals('evidence_coursecompleted', $ev2->get_descidentifier());
2270 $this->assertEquals('tool_lp', $ev2->get_desccomponent());
2271 $this->assertEquals($course->shortname, $ev2->get_desca());
2272 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev2->get_url());
2273 $this->assertEquals(null, $ev2->get_grade());
2274 $this->assertEquals($coursectx->id, $ev2->get_contextid());
2275 $this->assertEquals(\tool_lp\evidence::ACTION_LOG, $ev2->get_action());
2276 $this->assertEquals(null, $ev2->get_actionuserid());
2277
2278 // Outcome recommend.
2279 $uc3 = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c3->get_id()));
2280 $ev3 = \tool_lp\evidence::get_record(array('usercompetencyid' => $uc3->get_id()));
2281
2282 $this->assertEquals(null, $uc3->get_grade());
2283 $this->assertEquals(null, $uc3->get_proficiency());
2284 $this->assertEquals(\tool_lp\user_competency::STATUS_WAITING_FOR_REVIEW, $uc3->get_status());
2285
2286 $this->assertEquals('evidence_coursecompleted', $ev3->get_descidentifier());
2287 $this->assertEquals('tool_lp', $ev3->get_desccomponent());
2288 $this->assertEquals($course->shortname, $ev3->get_desca());
2289 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev3->get_url());
2290 $this->assertEquals(null, $ev3->get_grade());
2291 $this->assertEquals($coursectx->id, $ev3->get_contextid());
2292 $this->assertEquals(\tool_lp\evidence::ACTION_LOG, $ev3->get_action());
2293 $this->assertEquals(null, $ev3->get_actionuserid());
2294
2295 // Outcome complete.
2296 $uc4 = \tool_lp\user_competency::get_record(array('userid' => $u1->id, 'competencyid' => $c4->get_id()));
2297 $ev4 = \tool_lp\evidence::get_record(array('usercompetencyid' => $uc4->get_id()));
2298
2299 $this->assertEquals(3, $uc4->get_grade());
2300 $this->assertEquals(1, $uc4->get_proficiency());
2301 $this->assertEquals(\tool_lp\user_competency::STATUS_IDLE, $uc4->get_status());
2302
2303 $this->assertEquals('evidence_coursecompleted', $ev4->get_descidentifier());
2304 $this->assertEquals('tool_lp', $ev4->get_desccomponent());
2305 $this->assertEquals($course->shortname, $ev4->get_desca());
2306 $this->assertStringEndsWith('/report/completion/index.php?course=' . $course->id, $ev4->get_url());
2307 $this->assertEquals(3, $ev4->get_grade());
2308 $this->assertEquals($coursectx->id, $ev4->get_contextid());
2309 $this->assertEquals(\tool_lp\evidence::ACTION_COMPLETE, $ev4->get_action());
2310 $this->assertEquals(null, $ev4->get_actionuserid());
4c0e8167 2311 }
d4c0a2f6
SG
2312
2313 /**
2314 * Test update ruleoutcome for course_competency.
2315 */
d660824b 2316 public function test_set_ruleoutcome_course_competency() {
d4c0a2f6
SG
2317 $this->resetAfterTest(true);
2318 $dg = $this->getDataGenerator();
2319 $lpg = $dg->get_plugin_generator('tool_lp');
2320 $u1 = $dg->create_user();
2321 $u2 = $dg->create_user();
d660824b 2322 $course = $dg->create_course();
d4c0a2f6
SG
2323
2324 $this->setAdminUser();
2325 $f = $lpg->create_framework();
2326 $c = $lpg->create_competency(array('competencyframeworkid' => $f->get_id()));
d660824b 2327 $cc = api::add_competency_to_course($course->id, $c->get_id());
d4c0a2f6
SG
2328
2329 // Check record was created with default rule value Evidence.
2330 $this->assertEquals(1, \tool_lp\course_competency::count_records());
d660824b
FM
2331 $recordscc = api::list_course_competencies($course->id);
2332 $this->assertEquals(\tool_lp\course_competency::OUTCOME_EVIDENCE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
d4c0a2f6
SG
2333
2334 // Check ruleoutcome value is updated to None.
d660824b
FM
2335 $this->assertTrue(api::set_course_competency_ruleoutcome($recordscc[0]['coursecompetency']->get_id(),
2336 \tool_lp\course_competency::OUTCOME_NONE));
2337 $recordscc = api::list_course_competencies($course->id);
2338 $this->assertEquals(\tool_lp\course_competency::OUTCOME_NONE, $recordscc[0]['coursecompetency']->get_ruleoutcome());
d4c0a2f6
SG
2339 }
2340
4de456cd
SG
2341 /**
2342 * Test validation on grade on user_competency.
2343 */
2344 public function test_validate_grade_in_user_competency() {
2345 global $DB;
2346
2347 $this->resetAfterTest(true);
2348 $this->setAdminUser();
2349 $dg = $this->getDataGenerator();
2350 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2351 $user = $dg->create_user();
2352
2353 $dg->create_scale(array("id" => "1", "scale" => "value1, value2"));
2354 $dg->create_scale(array("id" => "2", "scale" => "value3, value4, value5, value6"));
2355
2356 $scaleconfiguration1 = '[{"scaleid":"1"},{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
2357 '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
2358 $scaleconfiguration2 = '[{"scaleid":"2"},{"name":"value3","id":1,"scaledefault":1,"proficient":0},'
2359 . '{"name":"value4","id":2,"scaledefault":0,"proficient":1},'
2360 . '{"name":"value5","id":3,"scaledefault":0,"proficient":0},'
2361 . '{"name":"value6","id":4,"scaledefault":0,"proficient":0}]';
2362
2363 // Create a framework with scale configuration1.
2364 $frm = array(
2365 'scaleid' => 1,
2366 'scaleconfiguration' => $scaleconfiguration1
2367 );
2368 $framework = $lpg->create_framework($frm);
2369 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2370
2371 // Create competency with its own scale configuration.
2372 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id(),
2373 'scaleid' => 2,
2374 'scaleconfiguration' => $scaleconfiguration2
2375 ));
2376
2377 // Detecte invalid grade in competency using its framework competency scale.
2378 try {
2379 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get_id(),
2380 'proficiency' => true, 'grade' => 3 ));
2381 $usercompetency->create();
2382 $this->fail('Invalid grade not detected in framework scale');
2383 } catch (\tool_lp\invalid_persistent_exception $e) {
2384 $this->assertTrue(true);
2385 }
2386
2387 // Detecte invalid grade in competency using its own scale.
2388 try {
2389 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get_id(),
2390 'proficiency' => true, 'grade' => 5 ));
2391 $usercompetency->create();
2392 $this->fail('Invalid grade not detected in competency scale');
2393 } catch (\tool_lp\invalid_persistent_exception $e) {
2394 $this->assertTrue(true);
2395 }
2396
2397 // Accept valid grade in competency using its framework competency scale.
2398 try {
2399 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c1->get_id(),
2400 'proficiency' => true, 'grade' => 1 ));
2401 $usercompetency->create();
2402 $this->assertTrue(true);
2403 } catch (\tool_lp\invalid_persistent_exception $e) {
2404 $this->fail('Valide grade rejected in framework scale');
2405 }
2406
2407 // Accept valid grade in competency using its framework competency scale.
2408 try {
2409 $usercompetency = new user_competency(0, (object) array('userid' => $user->id, 'competencyid' => $c2->get_id(),
2410 'proficiency' => true, 'grade' => 4 ));
2411 $usercompetency->create();
2412 $this->assertTrue(true);
2413 } catch (\tool_lp\invalid_persistent_exception $e) {
4de456cd
SG
2414 $this->fail('Valide grade rejected in competency scale');
2415 }
2416 }
2417
964afa98
IT
2418 /**
2419 * Test when adding competency that belong to hidden framework to plan/template/course.
2420 */
2421 public function test_hidden_framework() {
2422 $this->resetAfterTest(true);
2423 $this->setAdminUser();
2424 $dg = $this->getDataGenerator();
2425 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2426 $user = $dg->create_user();
2427
2428 // Create a course.
2429 $cat1 = $dg->create_category();
2430 $course = $dg->create_course(array('category' => $cat1->id));
2431 // Create a template.
2432 $template = $lpg->create_template();
2433 // Create a plan.
2434 $plan = $lpg->create_plan(array('userid' => $user->id));
2435
2436 // Create a hidden framework.
2437 $frm = array(
2438 'visible' => false
2439 );
2440 $framework = $lpg->create_framework($frm);
2441 $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2442
2443 // Linking competency that belong to hidden framework to course.
2444 try {
2445 api::add_competency_to_course($course->id, $competency->get_id());
2446 $this->fail('A competency belonging to hidden framework can not be linked to course');
2447 } catch (coding_exception $e) {
2448 $this->assertTrue(true);
2449 }
2450
2451 // Adding competency that belong to hidden framework to template.
2452 try {
2453 api::add_competency_to_template($template->get_id(), $competency->get_id());
2454 $this->fail('A competency belonging to hidden framework can not be added to template');
2455 } catch (coding_exception $e) {
2456 $this->assertTrue(true);
2457 }
2458
2459 // Adding competency that belong to hidden framework to plan.
2460 try {
2461 api::add_competency_to_plan($plan->get_id(), $competency->get_id());
2462 $this->fail('A competency belonging to hidden framework can not be added to plan');
2463 } catch (coding_exception $e) {
2464 $this->assertTrue(true);
2465 }
2466 }
2467
2468 /**
2469 * Test when using hidden template in plan/cohort.
2470 */
2471 public function test_hidden_template() {
2472 $this->resetAfterTest(true);
2473 $this->setAdminUser();
2474 $dg = $this->getDataGenerator();
2475 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2476 $user = $dg->create_user();
2477
2478 // Create a cohort.
2479 $cohort = $dg->create_cohort();
2480 // Create a hidden template.
2481 $template = $lpg->create_template(array('visible' => false));
2482
2483 // Can not link hidden template to plan.
2484 try {
2485 api::create_plan_from_template($template->get_id(), $user->id);
2486 $this->fail('Can not link a hidden template to plan');
2487 } catch (coding_exception $e) {
2488 $this->assertTrue(true);
2489 }
2490
2491 // Can associate hidden template to cohort.
2492 $templatecohort = api::create_template_cohort($template->get_id(), $cohort->id);
2493 $this->assertInstanceOf('\tool_lp\template_cohort', $templatecohort);
2494 }
2495
d3275795
SG
2496 /**
2497 * Test that completed plan created form a template does not change when template is modified.
2498 */
2499 public function test_completed_plan_doesnot_change() {
2500 global $DB;
2501
2502 $this->resetAfterTest(true);
2503 $this->setAdminUser();
2504 $dg = $this->getDataGenerator();
2505 $lpg = $this->getDataGenerator()->get_plugin_generator('tool_lp');
2506 $user = $dg->create_user();
2507
2508 // Create a framework and assign competencies.
2509 $framework = $lpg->create_framework();
2510 $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2511 $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2512 $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2513 $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id()));
2514
2515 // Create template and assign competencies.
2516 $tp = $lpg->create_template();
2517 $tpc1 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c1->get_id()));
2518 $tpc2 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c2->get_id()));
2519 $tpc3 = $lpg->create_template_competency(array('templateid' => $tp->get_id(), 'competencyid' => $c3->get_id()));
2520
2521 // Create a plan form template and change it status to complete.
2522 $plan = $lpg->create_plan(array('userid' => $user->id, 'templateid' => $tp->get_id()));
2523 api::complete_plan($plan);
2524
2525 // Check user competency plan created correctly.
2526 $this->assertEquals(3, \tool_lp\user_competency_plan::count_records());
2527 $ucp = \tool_lp\user_competency_plan::get_records();
2528 $this->assertEquals($ucp[0]->get_competencyid(), $c1->get_id());
2529 $this->assertEquals($ucp[1]->get_competencyid(), $c2->get_id());
2530 $this->assertEquals($ucp[2]->get_competencyid(), $c3->get_id());
2531
2532 // Add and remove a competency from the template.
2533 api::add_competency_to_template($tp->get_id(), $c4->get_id());
2534 api::remove_competency_from_template($tp->get_id(), $c1->get_id());
2535
2536 // Check that user competency plan did not change.
2537 $competencies = $plan->get_competencies();
2538 $this->assertEquals(3, count($competencies));
2539 $ucp1 = array($c1->get_id(), $c2->get_id(), $c3->get_id());
2540 $ucp2 = array();
2541 foreach ($competencies as $id => $cmp) {
2542 $ucp2[] = $id;
2543 }
2544 $this->assertEquals(0, count(array_diff($ucp1, $ucp2)));
2545 }
20c2fe3e
FM
2546
2547 protected function setup_framework_for_reset_rules_tests() {
2548 $this->resetAfterTest(true);
2549 $dg = $this->getDataGenerator();
2550 $lpg = $dg->get_plugin_generator('tool_lp');
2551
2552 $this->setAdminUser();
2553 $f1 = $lpg->create_framework();
2554 $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2555 $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1->get_id()));
2556 $c1a1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a->get_id()));
2557 $c1a1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1a1->get_id()));
2558 $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2559 $c1b1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b->get_id()));
2560 $c1b1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id(), 'parentid' => $c1b1->get_id()));
2561 $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2562 $c2a = $lpg->create_competency(array('competencyframeworkid' => $f1->get_id()));
2563
2564 $c1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2565 $c1->set_ruletype('tool_lp\\competency_rule_all');
2566 $c1->update();
2567 $c1a->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2568 $c1a->set_ruletype('tool_lp\\competency_rule_all');
2569 $c1a->update();
2570 $c1a1->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2571 $c1a1->set_ruletype('tool_lp\\competency_rule_all');
2572 $c1a1->update();
2573 $c1b->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2574 $c1b->set_ruletype('tool_lp\\competency_rule_all');
2575 $c1b->update();
2576 $c2->set_ruleoutcome(competency::OUTCOME_EVIDENCE);
2577 $c2->set_ruletype('tool_lp\\competency_rule_all');
2578 $c2->update();
2579
2580 return array(
2581 'f1' => $f1,
2582 'c1' => $c1,
2583 'c1a' => $c1a,
2584 'c1a1' => $c1a1,
2585 'c1a1a' => $c1a1a,
2586 'c1b' => $c1b,
2587 'c1b1' => $c1b1,
2588 'c1b1a' => $c1b1a,
2589 'c2' => $c2,
2590 'c2a' => $c2a,
2591 );
2592 }
2593
2594 public function test_moving_competency_reset_rules_updown() {
2595 extract($this->setup_framework_for_reset_rules_tests());
2596
2597 // Moving up and down doesn't change anything.
2598 api::move_down_competency($c1a->get_id());
2599 $c1->read();
2600 $c1a->read();
2601 $c1a1->read();
2602 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2603 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2604 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2605 api::move_up_competency($c1a->get_id());
2606 $c1->read();
2607 $c1a->read();
2608 $c1a1->read();
2609 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2610 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2611 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2612 }
2613
2614 public function test_moving_competency_reset_rules_parent() {
2615 extract($this->setup_framework_for_reset_rules_tests());
2616
2617 // Moving out of parent will reset the parent, and the destination.
2618 api::set_parent_competency($c1a->get_id(), $c1b->get_id());
2619 $c1->read();
2620 $c1a->read();
2621 $c1a1->read();
2622 $c1b->read();
2623 $c2->read();
2624 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
2625 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2626 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2627 $this->assertEquals(competency::OUTCOME_NONE, $c1b->get_ruleoutcome());
2628 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2629 }
2630
2631 public function test_moving_competency_reset_rules_totoplevel() {
2632 extract($this->setup_framework_for_reset_rules_tests());
2633
2634 // Moving to top level only affects the initial parent.
2635 api::set_parent_competency($c1a1->get_id(), 0);
2636 $c1->read();
2637 $c1a->read();
2638 $c1a1->read();
2639 $c1b->read();
2640 $c2->read();
2641 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2642 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get_ruleoutcome());
2643 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2644 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2645 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2646 }
2647
2648 public function test_moving_competency_reset_rules_fromtoplevel() {
2649 extract($this->setup_framework_for_reset_rules_tests());
2650
2651 // Moving from top level only affects the destination parent.
2652 api::set_parent_competency($c2->get_id(), $c1a1->get_id());
2653 $c1->read();
2654 $c1a->read();
2655 $c1a1->read();
2656 $c1b->read();
2657 $c2->read();
2658 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1->get_ruleoutcome());
2659 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2660 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get_ruleoutcome());
2661 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2662 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2663 }
2664
2665 public function test_moving_competency_reset_rules_child() {
2666 extract($this->setup_framework_for_reset_rules_tests());
2667
2668 // Moving to a child of self resets self, parent and destination.
2669 api::set_parent_competency($c1a->get_id(), $c1a1->get_id());
2670 $c1->read();
2671 $c1a->read();
2672 $c1a1->read();
2673 $c1b->read();
2674 $c2->read();
2675 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
2676 $this->assertEquals(competency::OUTCOME_NONE, $c1a->get_ruleoutcome());
2677 $this->assertEquals(competency::OUTCOME_NONE, $c1a1->get_ruleoutcome());
2678 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2679 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2680 }
2681
2682 public function test_create_competency_reset_rules() {
2683 extract($this->setup_framework_for_reset_rules_tests());
2684
2685 // Adding a new competency resets the rule of its parent.
2686 api::create_competency((object) array('shortname' => 'A', 'parentid' => $c1->get_id(), 'idnumber' => 'A',
2687 'competencyframeworkid' => $f1->get_id()));
2688 $c1->read();
2689 $c1a->read();
2690 $c1a1->read();
2691 $c1b->read();
2692 $c2->read();
2693 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
2694 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a->get_ruleoutcome());
2695 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1a1->get_ruleoutcome());
2696 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2697 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2698 }
2699
2700 public function test_delete_competency_reset_rules() {
2701 extract($this->setup_framework_for_reset_rules_tests());
2702
2703 // Deleting a competency resets the rule of its parent.
2704 api::delete_competency($c1a->get_id());
2705 $c1->read();
2706 $c1b->read();
2707 $c2->read();
2708 $this->assertEquals(competency::OUTCOME_NONE, $c1->get_ruleoutcome());
2709 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c1b->get_ruleoutcome());
2710 $this->assertEquals(competency::OUTCOME_EVIDENCE, $c2->get_ruleoutcome());
2711 }
f610a957 2712}