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