[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/competency/tests/ -> api_test.php (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1