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