Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

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