See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body