Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * External tests.
  19   *
  20   * @package    core_competency
  21   * @copyright  2016 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  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  29  
  30  use core_competency\api;
  31  use core_competency\course_competency_settings;
  32  use core_competency\external;
  33  use core_competency\invalid_persistent_exception;
  34  use core_competency\plan;
  35  use core_competency\plan_competency;
  36  use core_competency\related_competency;
  37  use core_competency\template;
  38  use core_competency\template_competency;
  39  use core_competency\user_competency;
  40  use core_competency\user_competency_plan;
  41  
  42  /**
  43   * External testcase.
  44   *
  45   * @package    core_competency
  46   * @copyright  2016 Frédéric Massart - FMCorz.net
  47   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  48   */
  49  class core_competency_external_testcase extends externallib_advanced_testcase {
  50  
  51      /** @var stdClass $creator User with enough permissions to create insystem context. */
  52      protected $creator = null;
  53  
  54      /** @var stdClass $learningplancreator User with enough permissions to create incategory context. */
  55      protected $catcreator = null;
  56  
  57      /** @var stdClass $category Category */
  58      protected $category = null;
  59  
  60      /** @var stdClass $user User with enough permissions to view insystem context */
  61      protected $user = null;
  62  
  63      /** @var stdClass $catuser User with enough permissions to view incategory context */
  64      protected $catuser = null;
  65  
  66      /** @var int Creator role id */
  67      protected $creatorrole = null;
  68  
  69      /** @var int User role id */
  70      protected $userrole = null;
  71  
  72      /** @var stdClass $scale1 Scale */
  73      protected $scale1 = null;
  74  
  75      /** @var stdClass $scale2 Scale */
  76      protected $scale2 = null;
  77  
  78      /** @var stdClass $scale3 Scale */
  79      protected $scale3 = null;
  80  
  81      /** @var stdClass $scale4 Scale */
  82      protected $scale4 = null;
  83  
  84      /** @var string scaleconfiguration */
  85      protected $scaleconfiguration1 = null;
  86  
  87      /** @var string scaleconfiguration */
  88      protected $scaleconfiguration2 = null;
  89  
  90      /** @var string catscaleconfiguration */
  91      protected $scaleconfiguration3 = null;
  92  
  93      /** @var string catscaleconfiguration */
  94      protected $catscaleconfiguration4 = null;
  95  
  96      /**
  97       * Setup function- we will create a course and add an assign instance to it.
  98       */
  99      protected function setUp() {
 100          global $DB, $CFG;
 101  
 102          $this->resetAfterTest(true);
 103  
 104          // Create some users.
 105          $creator = $this->getDataGenerator()->create_user();
 106          $user = $this->getDataGenerator()->create_user();
 107          $catuser = $this->getDataGenerator()->create_user();
 108          $category = $this->getDataGenerator()->create_category();
 109          $othercategory = $this->getDataGenerator()->create_category();
 110          $catcreator = $this->getDataGenerator()->create_user();
 111  
 112          $syscontext = context_system::instance();
 113          $catcontext = context_coursecat::instance($category->id);
 114          $othercatcontext = context_coursecat::instance($othercategory->id);
 115  
 116          // Fetching default authenticated user role.
 117          $authrole = $DB->get_record('role', array('id' => $CFG->defaultuserroleid));
 118  
 119          // Reset all default authenticated users permissions.
 120          unassign_capability('moodle/competency:competencygrade', $authrole->id);
 121          unassign_capability('moodle/competency:competencymanage', $authrole->id);
 122          unassign_capability('moodle/competency:competencyview', $authrole->id);
 123          unassign_capability('moodle/competency:planmanage', $authrole->id);
 124          unassign_capability('moodle/competency:planmanagedraft', $authrole->id);
 125          unassign_capability('moodle/competency:planmanageown', $authrole->id);
 126          unassign_capability('moodle/competency:planview', $authrole->id);
 127          unassign_capability('moodle/competency:planviewdraft', $authrole->id);
 128          unassign_capability('moodle/competency:planviewown', $authrole->id);
 129          unassign_capability('moodle/competency:planviewowndraft', $authrole->id);
 130          unassign_capability('moodle/competency:templatemanage', $authrole->id);
 131          unassign_capability('moodle/competency:templateview', $authrole->id);
 132          unassign_capability('moodle/cohort:manage', $authrole->id);
 133          unassign_capability('moodle/competency:coursecompetencyconfigure', $authrole->id);
 134  
 135          // Creating specific roles.
 136          $this->creatorrole = create_role('Creator role', 'creatorrole', 'learning plan creator role description');
 137          $this->userrole = create_role('User role', 'userrole', 'learning plan user role description');
 138  
 139          assign_capability('moodle/competency:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 140          assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 141          assign_capability('moodle/competency:competencyview', CAP_ALLOW, $this->userrole, $syscontext->id);
 142          assign_capability('moodle/competency:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 143          assign_capability('moodle/competency:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 144          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 145          assign_capability('moodle/competency:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 146          assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 147          assign_capability('moodle/competency:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 148          assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 149          assign_capability('moodle/cohort:manage', CAP_ALLOW, $this->creatorrole, $syscontext->id);
 150          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontext->id);
 151          assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id);
 152          assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
 153  
 154          role_assign($this->creatorrole, $creator->id, $syscontext->id);
 155          role_assign($this->creatorrole, $catcreator->id, $catcontext->id);
 156          role_assign($this->userrole, $user->id, $syscontext->id);
 157          role_assign($this->userrole, $catuser->id, $catcontext->id);
 158  
 159          $this->creator = $creator;
 160          $this->catcreator = $catcreator;
 161          $this->user = $user;
 162          $this->catuser = $catuser;
 163          $this->category = $category;
 164          $this->othercategory = $othercategory;
 165  
 166          $this->scale1 = $this->getDataGenerator()->create_scale(array("scale" => "value1, value2"));
 167          $this->scale2 = $this->getDataGenerator()->create_scale(array("scale" => "value3, value4"));
 168          $this->scale3 = $this->getDataGenerator()->create_scale(array("scale" => "value5, value6"));
 169          $this->scale4 = $this->getDataGenerator()->create_scale(array("scale" => "value7, value8"));
 170  
 171          $this->scaleconfiguration1 = '[{"scaleid":"'.$this->scale1->id.'"},' .
 172                  '{"name":"value1","id":1,"scaledefault":1,"proficient":0},' .
 173                  '{"name":"value2","id":2,"scaledefault":0,"proficient":1}]';
 174          $this->scaleconfiguration2 = '[{"scaleid":"'.$this->scale2->id.'"},' .
 175                  '{"name":"value3","id":1,"scaledefault":1,"proficient":0},' .
 176                  '{"name":"value4","id":2,"scaledefault":0,"proficient":1}]';
 177          $this->scaleconfiguration3 = '[{"scaleid":"'.$this->scale3->id.'"},' .
 178                  '{"name":"value5","id":1,"scaledefault":1,"proficient":0},' .
 179                  '{"name":"value6","id":2,"scaledefault":0,"proficient":1}]';
 180          $this->scaleconfiguration4 = '[{"scaleid":"'.$this->scale4->id.'"},'.
 181                  '{"name":"value8","id":1,"scaledefault":1,"proficient":0},' .
 182                  '{"name":"value8","id":2,"scaledefault":0,"proficient":1}]';
 183          accesslib_clear_all_caches_for_unit_testing();
 184      }
 185  
 186  
 187      protected function create_competency_framework($number = 1, $system = true) {
 188          $scalename = 'scale' . $number;
 189          $scalepropname = 'scaleconfiguration' . $number;
 190          $framework = array(
 191              'shortname' => 'shortname' . $number,
 192              'idnumber' => 'idnumber' . $number,
 193              'description' => 'description' . $number,
 194              'descriptionformat' => FORMAT_HTML,
 195              'scaleid' => $this->$scalename->id,
 196              'scaleconfiguration' => $this->$scalepropname,
 197              'visible' => true,
 198              'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
 199          );
 200          $result = external::create_competency_framework($framework);
 201          return (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result);
 202      }
 203  
 204      protected function create_plan($number, $userid, $templateid, $status, $duedate) {
 205          $plan = array(
 206              'name' => 'name' . $number,
 207              'description' => 'description' . $number,
 208              'descriptionformat' => FORMAT_HTML,
 209              'userid' => $userid,
 210              'templateid' => empty($templateid) ? null : $templateid,
 211              'status' => $status,
 212              'duedate' => $duedate
 213          );
 214          $result = external::create_plan($plan);
 215          return (object) external_api::clean_returnvalue(external::create_plan_returns(), $result);
 216      }
 217  
 218      protected function create_template($number, $system) {
 219          $template = array(
 220              'shortname' => 'shortname' . $number,
 221              'description' => 'description' . $number,
 222              'descriptionformat' => FORMAT_HTML,
 223              'duedate' => 0,
 224              'visible' => true,
 225              'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
 226          );
 227          $result = external::create_template($template);
 228          return (object) external_api::clean_returnvalue(external::create_template_returns(), $result);
 229      }
 230  
 231      protected function update_template($templateid, $number) {
 232          $template = array(
 233              'id' => $templateid,
 234              'shortname' => 'shortname' . $number,
 235              'description' => 'description' . $number,
 236              'descriptionformat' => FORMAT_HTML,
 237              'visible' => true
 238          );
 239          $result = external::update_template($template);
 240          return external_api::clean_returnvalue(external::update_template_returns(), $result);
 241      }
 242  
 243      protected function update_plan($planid, $number, $userid, $templateid, $status, $duedate) {
 244          $plan = array(
 245              'id' => $planid,
 246              'name' => 'name' . $number,
 247              'description' => 'description' . $number,
 248              'descriptionformat' => FORMAT_HTML,
 249              'userid' => $userid,
 250              'templateid' => $templateid,
 251              'status' => $status,
 252              'duedate' => $duedate
 253          );
 254          $result = external::update_plan($plan);
 255          return external_api::clean_returnvalue(external::update_plan_returns(), $result);
 256      }
 257  
 258      protected function update_competency_framework($id, $number = 1, $system = true) {
 259          $scalename = 'scale' . $number;
 260          $scalepropname = 'scaleconfiguration' . $number;
 261          $framework = array(
 262              'id' => $id,
 263              'shortname' => 'shortname' . $number,
 264              'idnumber' => 'idnumber' . $number,
 265              'description' => 'description' . $number,
 266              'descriptionformat' => FORMAT_HTML,
 267              'scaleid' => $this->$scalename->id,
 268              'scaleconfiguration' => $this->$scalepropname,
 269              'visible' => true,
 270              'contextid' => $system ? context_system::instance()->id : context_coursecat::instance($this->category->id)->id
 271          );
 272          $result = external::update_competency_framework($framework);
 273          return external_api::clean_returnvalue(external::update_competency_framework_returns(), $result);
 274      }
 275  
 276      protected function create_competency($number, $frameworkid) {
 277          $competency = array(
 278              'shortname' => 'shortname' . $number,
 279              'idnumber' => 'idnumber' . $number,
 280              'description' => 'description' . $number,
 281              'descriptionformat' => FORMAT_HTML,
 282              'competencyframeworkid' => $frameworkid
 283          );
 284          $result = external::create_competency($competency);
 285          return (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
 286      }
 287  
 288      protected function update_competency($id, $number) {
 289          $competency = array(
 290              'id' => $id,
 291              'shortname' => 'shortname' . $number,
 292              'idnumber' => 'idnumber' . $number,
 293              'description' => 'description' . $number,
 294              'descriptionformat' => FORMAT_HTML
 295          );
 296          $result = external::update_competency($competency);
 297          return external_api::clean_returnvalue(external::update_competency_returns(), $result);
 298      }
 299  
 300      /**
 301       * Test we can't create a competency framework with only read permissions.
 302       *
 303       * @expectedException required_capability_exception
 304       */
 305      public function test_create_competency_frameworks_with_read_permissions() {
 306          $this->setUser($this->user);
 307  
 308          $result = $this->create_competency_framework(1, true);
 309      }
 310  
 311      /**
 312       * Test we can't create a competency framework with only read permissions.
 313       *
 314       * @expectedException required_capability_exception
 315       */
 316      public function test_create_competency_frameworks_with_read_permissions_in_category() {
 317          $this->setUser($this->catuser);
 318          $result = $this->create_competency_framework(1, false);
 319      }
 320  
 321      /**
 322       * Test we can create a competency framework with manage permissions.
 323       */
 324      public function test_create_competency_frameworks_with_manage_permissions() {
 325          $this->setUser($this->creator);
 326          $result = $this->create_competency_framework(1, true);
 327  
 328          $this->assertGreaterThan(0, $result->timecreated);
 329          $this->assertGreaterThan(0, $result->timemodified);
 330          $this->assertEquals($this->creator->id, $result->usermodified);
 331          $this->assertEquals('shortname1', $result->shortname);
 332          $this->assertEquals('idnumber1', $result->idnumber);
 333          $this->assertEquals('description1', $result->description);
 334          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 335          $this->assertEquals($this->scale1->id, $result->scaleid);
 336          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 337          $this->assertEquals(true, $result->visible);
 338      }
 339  
 340      /**
 341       * Test we can create a competency framework with manage permissions.
 342       */
 343      public function test_create_competency_frameworks_with_manage_permissions_in_category() {
 344          $this->setUser($this->catcreator);
 345          $result = $this->create_competency_framework(1, false);
 346  
 347          $this->assertGreaterThan(0, $result->timecreated);
 348          $this->assertGreaterThan(0, $result->timemodified);
 349          $this->assertEquals($this->catcreator->id, $result->usermodified);
 350          $this->assertEquals('shortname1', $result->shortname);
 351          $this->assertEquals('idnumber1', $result->idnumber);
 352          $this->assertEquals('description1', $result->description);
 353          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 354          $this->assertEquals($this->scale1->id, $result->scaleid);
 355          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 356          $this->assertEquals(true, $result->visible);
 357  
 358          try {
 359              $result = $this->create_competency_framework(1, true);
 360              $this->fail('User cannot create a framework at system level.');
 361          } catch (required_capability_exception $e) {
 362              // All good.
 363          }
 364      }
 365  
 366      /**
 367       * Test we cannot create a competency framework with nasty data.
 368       *
 369       * @expectedException invalid_parameter_exception
 370       */
 371      public function test_create_competency_frameworks_with_nasty_data() {
 372          $this->setUser($this->creator);
 373          $framework = array(
 374              'shortname' => 'short<a href="">',
 375              'idnumber' => 'id;"number',
 376              'description' => 'de<>\\..scription',
 377              'descriptionformat' => FORMAT_HTML,
 378              'scaleid' => $this->scale1->id,
 379              'scaleconfiguration' => $this->scaleconfiguration1,
 380              'visible' => true,
 381              'contextid' => context_system::instance()->id
 382          );
 383          $result = external::create_competency_framework($framework);
 384      }
 385  
 386      /**
 387       * Test we can read a competency framework with manage permissions.
 388       */
 389      public function test_read_competency_frameworks_with_manage_permissions() {
 390          $this->setUser($this->creator);
 391          $result = $this->create_competency_framework(1, true);
 392  
 393          $id = $result->id;
 394          $result = external::read_competency_framework($id);
 395          $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
 396  
 397          $this->assertGreaterThan(0, $result->timecreated);
 398          $this->assertGreaterThan(0, $result->timemodified);
 399          $this->assertEquals($this->creator->id, $result->usermodified);
 400          $this->assertEquals('shortname1', $result->shortname);
 401          $this->assertEquals('idnumber1', $result->idnumber);
 402          $this->assertEquals('description1', $result->description);
 403          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 404          $this->assertEquals($this->scale1->id, $result->scaleid);
 405          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 406          $this->assertEquals(true, $result->visible);
 407      }
 408  
 409      /**
 410       * Test we can read a competency framework with manage permissions.
 411       */
 412      public function test_read_competency_frameworks_with_manage_permissions_in_category() {
 413          $this->setUser($this->creator);
 414  
 415          $insystem = $this->create_competency_framework(1, true);
 416          $incat = $this->create_competency_framework(2, false);
 417  
 418          $this->setUser($this->catcreator);
 419          $id = $incat->id;
 420          $result = external::read_competency_framework($id);
 421          $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
 422  
 423          $this->assertGreaterThan(0, $result->timecreated);
 424          $this->assertGreaterThan(0, $result->timemodified);
 425          $this->assertEquals($this->creator->id, $result->usermodified);
 426          $this->assertEquals('shortname2', $result->shortname);
 427          $this->assertEquals('idnumber2', $result->idnumber);
 428          $this->assertEquals('description2', $result->description);
 429          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 430          $this->assertEquals($this->scale2->id, $result->scaleid);
 431          $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
 432          $this->assertEquals(true, $result->visible);
 433  
 434          try {
 435              $id = $insystem->id;
 436              $result = external::read_competency_framework($id);
 437              $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
 438              $this->fail('User cannot read a framework at system level.');
 439          } catch (required_capability_exception $e) {
 440              // All good.
 441          }
 442      }
 443  
 444      /**
 445       * Test we can read a competency framework with read permissions.
 446       */
 447      public function test_read_competency_frameworks_with_read_permissions() {
 448          $this->setUser($this->creator);
 449          $result = $this->create_competency_framework(1, true);
 450  
 451          // Switch users to someone with less permissions.
 452          $this->setUser($this->user);
 453          $id = $result->id;
 454          $result = external::read_competency_framework($id);
 455          $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
 456  
 457          $this->assertGreaterThan(0, $result->timecreated);
 458          $this->assertGreaterThan(0, $result->timemodified);
 459          $this->assertEquals($this->creator->id, $result->usermodified);
 460          $this->assertEquals('shortname1', $result->shortname);
 461          $this->assertEquals('idnumber1', $result->idnumber);
 462          $this->assertEquals('description1', $result->description);
 463          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 464          $this->assertEquals($this->scale1->id, $result->scaleid);
 465          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 466          $this->assertEquals(true, $result->visible);
 467      }
 468      /**
 469       * Test we can read a competency framework with read permissions.
 470       */
 471      public function test_read_competency_frameworks_with_read_permissions_in_category() {
 472          $this->setUser($this->creator);
 473  
 474          $insystem = $this->create_competency_framework(1, true);
 475          $incat = $this->create_competency_framework(2, false);
 476  
 477          // Switch users to someone with less permissions.
 478          $this->setUser($this->catuser);
 479          $id = $incat->id;
 480          $result = external::read_competency_framework($id);
 481          $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result);
 482  
 483          $this->assertGreaterThan(0, $result->timecreated);
 484          $this->assertGreaterThan(0, $result->timemodified);
 485          $this->assertEquals($this->creator->id, $result->usermodified);
 486          $this->assertEquals('shortname2', $result->shortname);
 487          $this->assertEquals('idnumber2', $result->idnumber);
 488          $this->assertEquals('description2', $result->description);
 489          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 490          $this->assertEquals($this->scale2->id, $result->scaleid);
 491          $this->assertEquals($this->scaleconfiguration2, $result->scaleconfiguration);
 492          $this->assertEquals(true, $result->visible);
 493  
 494          // Switching to user with no permissions.
 495          try {
 496              $result = external::read_competency_framework($insystem->id);
 497              $this->fail('Current user cannot should not be able to read the framework.');
 498          } catch (required_capability_exception $e) {
 499              // All good.
 500          }
 501      }
 502  
 503      /**
 504       * Test we can delete a competency framework with manage permissions.
 505       */
 506      public function test_delete_competency_frameworks_with_manage_permissions() {
 507          $this->setUser($this->creator);
 508          $result = $this->create_competency_framework(1, true);
 509  
 510          $id = $result->id;
 511          $result = external::delete_competency_framework($id);
 512          $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
 513  
 514          $this->assertTrue($result);
 515      }
 516  
 517      /**
 518       * Test we can delete a competency framework with manage permissions.
 519       */
 520      public function test_delete_competency_frameworks_with_manage_permissions_in_category() {
 521          $this->setUser($this->creator);
 522  
 523          $insystem = $this->create_competency_framework(1, true);
 524          $incat = $this->create_competency_framework(2, false);
 525  
 526          $this->setUser($this->catcreator);
 527          $id = $incat->id;
 528          $result = external::delete_competency_framework($id);
 529          $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
 530  
 531          $this->assertTrue($result);
 532  
 533          try {
 534              $id = $insystem->id;
 535              $result = external::delete_competency_framework($id);
 536              $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result);
 537              $this->fail('Current user cannot should not be able to delete the framework.');
 538          } catch (required_capability_exception $e) {
 539              // All good.
 540          }
 541      }
 542  
 543      /**
 544       * Test we can delete a competency framework with read permissions.
 545       *
 546       * @expectedException required_capability_exception
 547       */
 548      public function test_delete_competency_frameworks_with_read_permissions() {
 549          $this->setUser($this->creator);
 550          $result = $this->create_competency_framework(1, true);
 551  
 552          $id = $result->id;
 553          // Switch users to someone with less permissions.
 554          $this->setUser($this->user);
 555          $result = external::delete_competency_framework($id);
 556      }
 557  
 558      /**
 559       * Test we can update a competency framework with manage permissions.
 560       */
 561      public function test_update_competency_frameworks_with_manage_permissions() {
 562          $this->setUser($this->creator);
 563          $result = $this->create_competency_framework(1, true);
 564  
 565          $result = $this->update_competency_framework($result->id, 2, true);
 566  
 567          $this->assertTrue($result);
 568      }
 569  
 570      /**
 571       * Test we can update a competency framework with manage permissions.
 572       */
 573      public function test_update_competency_frameworks_with_manage_permissions_in_category() {
 574          $this->setUser($this->creator);
 575  
 576          $insystem = $this->create_competency_framework(1, true);
 577          $incat = $this->create_competency_framework(2, false);
 578  
 579          $this->setUser($this->catcreator);
 580          $id = $incat->id;
 581  
 582          $result = $this->update_competency_framework($incat->id, 3, false);
 583  
 584          $this->assertTrue($result);
 585  
 586          try {
 587              $result = $this->update_competency_framework($insystem->id, 4, true);
 588              $this->fail('Current user should not be able to update the framework.');
 589          } catch (required_capability_exception $e) {
 590              // All good.
 591          }
 592      }
 593  
 594      public function test_update_framework_scale() {
 595          $this->setUser($this->creator);
 596          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
 597  
 598          $s1 = $this->getDataGenerator()->create_scale();
 599  
 600          $f1 = $lpg->create_framework(array('scaleid' => $s1->id));
 601          $f2 = $lpg->create_framework(array('scaleid' => $s1->id));
 602          $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
 603          $c2 = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
 604  
 605          $this->assertEquals($s1->id, $f1->get('scaleid'));
 606  
 607          // Make the scale of f2 being used.
 608          $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2->get('id')));
 609  
 610          // Changing the framework where the scale is not used.
 611          $result = $this->update_competency_framework($f1->get('id'), 3, true);
 612  
 613          $f1 = new \core_competency\competency_framework($f1->get('id'));
 614          $this->assertEquals($this->scale3->id, $f1->get('scaleid'));
 615  
 616          // Changing the framework where the scale is used.
 617          try {
 618              $result = $this->update_competency_framework($f2->get('id'), 4, true);
 619              $this->fail('The scale cannot be changed once used.');
 620          } catch (\core\invalid_persistent_exception $e) {
 621              $this->assertRegexp('/scaleid/', $e->getMessage());
 622          }
 623      }
 624  
 625      /**
 626       * Test we can update a competency framework with read permissions.
 627       *
 628       * @expectedException required_capability_exception
 629       */
 630      public function test_update_competency_frameworks_with_read_permissions() {
 631          $this->setUser($this->creator);
 632          $result = $this->create_competency_framework(1, true);
 633  
 634          $this->setUser($this->user);
 635          $result = $this->update_competency_framework($result->id, 2, true);
 636      }
 637  
 638      /**
 639       * Test we can list and count competency frameworks with manage permissions.
 640       */
 641      public function test_list_and_count_competency_frameworks_with_manage_permissions() {
 642          $this->setUser($this->creator);
 643          $result = $this->create_competency_framework(1, true);
 644          $result = $this->create_competency_framework(2, true);
 645          $result = $this->create_competency_framework(3, true);
 646          $result = $this->create_competency_framework(4, false);
 647  
 648          $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
 649          $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
 650  
 651          $this->assertEquals($result, 3);
 652  
 653          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 654              array('contextid' => context_system::instance()->id), 'self', false);
 655          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 656  
 657          $this->assertEquals(count($result), 3);
 658          $result = (object) $result[0];
 659  
 660          $this->assertGreaterThan(0, $result->timecreated);
 661          $this->assertGreaterThan(0, $result->timemodified);
 662          $this->assertEquals($this->creator->id, $result->usermodified);
 663          $this->assertEquals('shortname1', $result->shortname);
 664          $this->assertEquals('idnumber1', $result->idnumber);
 665          $this->assertEquals('description1', $result->description);
 666          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 667          $this->assertEquals($this->scale1->id, $result->scaleid);
 668          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 669          $this->assertEquals(true, $result->visible);
 670      }
 671  
 672      public function test_list_competency_frameworks_with_query() {
 673          $this->setUser($this->creator);
 674          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
 675          $framework1 = $lpg->create_framework(array(
 676              'shortname' => 'shortname_beetroot',
 677              'idnumber' => 'idnumber_cinnamon',
 678              'description' => 'description',
 679              'descriptionformat' => FORMAT_HTML,
 680              'visible' => true,
 681              'contextid' => context_system::instance()->id
 682          ));
 683          $framework2 = $lpg->create_framework(array(
 684              'shortname' => 'shortname_citrus',
 685              'idnumber' => 'idnumber_beer',
 686              'description' => 'description',
 687              'descriptionformat' => FORMAT_HTML,
 688              'visible' => true,
 689              'contextid' => context_system::instance()->id
 690          ));
 691  
 692          // Search on both ID number and shortname.
 693          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 694              array('contextid' => context_system::instance()->id), 'self', false, 'bee');
 695          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 696          $this->assertCount(2, $result);
 697          $f = (object) array_shift($result);
 698          $this->assertEquals($framework1->get('id'), $f->id);
 699          $f = (object) array_shift($result);
 700          $this->assertEquals($framework2->get('id'), $f->id);
 701  
 702          // Search on ID number.
 703          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 704              array('contextid' => context_system::instance()->id), 'self', false, 'beer');
 705          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 706          $this->assertCount(1, $result);
 707          $f = (object) array_shift($result);
 708          $this->assertEquals($framework2->get('id'), $f->id);
 709  
 710          // Search on shortname.
 711          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 712              array('contextid' => context_system::instance()->id), 'self', false, 'cinnamon');
 713          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 714          $this->assertCount(1, $result);
 715          $f = (object) array_shift($result);
 716          $this->assertEquals($framework1->get('id'), $f->id);
 717  
 718          // No match.
 719          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 720              array('contextid' => context_system::instance()->id), 'self', false, 'pwnd!');
 721          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 722          $this->assertCount(0, $result);
 723      }
 724  
 725      /**
 726       * Test we can list and count competency frameworks with read permissions.
 727       */
 728      public function test_list_and_count_competency_frameworks_with_read_permissions() {
 729          $this->setUser($this->creator);
 730          $result = $this->create_competency_framework(1, true);
 731          $result = $this->create_competency_framework(2, true);
 732          $result = $this->create_competency_framework(3, true);
 733          $result = $this->create_competency_framework(4, false);
 734  
 735          $this->setUser($this->user);
 736          $result = external::count_competency_frameworks(array('contextid' => context_system::instance()->id), 'self');
 737          $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result);
 738          $this->assertEquals($result, 3);
 739  
 740          $result = external::list_competency_frameworks('shortname', 'ASC', 0, 10,
 741              array('contextid' => context_system::instance()->id), 'self', false);
 742          $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result);
 743  
 744          $this->assertEquals(count($result), 3);
 745          $result = (object) $result[0];
 746  
 747          $this->assertGreaterThan(0, $result->timecreated);
 748          $this->assertGreaterThan(0, $result->timemodified);
 749          $this->assertEquals($this->creator->id, $result->usermodified);
 750          $this->assertEquals('shortname1', $result->shortname);
 751          $this->assertEquals('idnumber1', $result->idnumber);
 752          $this->assertEquals('description1', $result->description);
 753          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 754          $this->assertEquals($this->scale1->id, $result->scaleid);
 755          $this->assertEquals($this->scaleconfiguration1, $result->scaleconfiguration);
 756          $this->assertEquals(true, $result->visible);
 757      }
 758  
 759      /**
 760       * Test we can't create a competency with only read permissions.
 761       *
 762       * @expectedException required_capability_exception
 763       */
 764      public function test_create_competency_with_read_permissions() {
 765          $framework = $this->getDataGenerator()->get_plugin_generator('core_competency')->create_framework();
 766          $this->setUser($this->user);
 767          $competency = $this->create_competency(1, $framework->get('id'));
 768      }
 769  
 770      /**
 771       * Test we can create a competency with manage permissions.
 772       */
 773      public function test_create_competency_with_manage_permissions() {
 774          $this->setUser($this->creator);
 775          $framework = $this->create_competency_framework(1, true);
 776          $competency = $this->create_competency(1, $framework->id);
 777  
 778          $this->assertGreaterThan(0, $competency->timecreated);
 779          $this->assertGreaterThan(0, $competency->timemodified);
 780          $this->assertEquals($this->creator->id, $competency->usermodified);
 781          $this->assertEquals('shortname1', $competency->shortname);
 782          $this->assertEquals('idnumber1', $competency->idnumber);
 783          $this->assertEquals('description1', $competency->description);
 784          $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
 785          $this->assertEquals(0, $competency->parentid);
 786          $this->assertEquals($framework->id, $competency->competencyframeworkid);
 787      }
 788  
 789  
 790      /**
 791       * Test we can create a competency with manage permissions.
 792       */
 793      public function test_create_competency_with_manage_permissions_in_category() {
 794          $this->setUser($this->creator);
 795  
 796          $insystem = $this->create_competency_framework(1, true);
 797          $incat = $this->create_competency_framework(2, false);
 798  
 799          $this->setUser($this->catcreator);
 800  
 801          $competency = $this->create_competency(1, $incat->id);
 802  
 803          $this->assertGreaterThan(0, $competency->timecreated);
 804          $this->assertGreaterThan(0, $competency->timemodified);
 805          $this->assertEquals($this->catcreator->id, $competency->usermodified);
 806          $this->assertEquals('shortname1', $competency->shortname);
 807          $this->assertEquals('idnumber1', $competency->idnumber);
 808          $this->assertEquals('description1', $competency->description);
 809          $this->assertEquals(FORMAT_HTML, $competency->descriptionformat);
 810          $this->assertEquals(0, $competency->parentid);
 811          $this->assertEquals($incat->id, $competency->competencyframeworkid);
 812  
 813          try {
 814              $competency = $this->create_competency(2, $insystem->id);
 815              $this->fail('User should not be able to create a competency in system context.');
 816          } catch (required_capability_exception $e) {
 817              // All good.
 818          }
 819      }
 820  
 821      /**
 822       * Test we cannot create a competency with nasty data.
 823       *
 824       * @expectedException invalid_parameter_exception
 825       */
 826      public function test_create_competency_with_nasty_data() {
 827          $this->setUser($this->creator);
 828          $framework = $this->create_competency_framework(1, true);
 829          $competency = array(
 830              'shortname' => 'shortname<a href="">',
 831              'idnumber' => 'id;"number',
 832              'description' => 'de<>\\..scription',
 833              'descriptionformat' => FORMAT_HTML,
 834              'competencyframeworkid' => $framework->id,
 835              'sortorder' => 0
 836          );
 837          $result = external::create_competency($competency);
 838          $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result);
 839      }
 840  
 841      /**
 842       * Test we can read a competency with manage permissions.
 843       */
 844      public function test_read_competencies_with_manage_permissions() {
 845          $this->setUser($this->creator);
 846          $framework = $this->create_competency_framework(1, true);
 847          $competency = $this->create_competency(1, $framework->id);
 848  
 849          $id = $competency->id;
 850          $result = external::read_competency($id);
 851          $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
 852  
 853          $this->assertGreaterThan(0, $result->timecreated);
 854          $this->assertGreaterThan(0, $result->timemodified);
 855          $this->assertEquals($this->creator->id, $result->usermodified);
 856          $this->assertEquals('shortname1', $result->shortname);
 857          $this->assertEquals('idnumber1', $result->idnumber);
 858          $this->assertEquals('description1', $result->description);
 859          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 860          $this->assertEquals(0, $result->parentid);
 861          $this->assertEquals($framework->id, $result->competencyframeworkid);
 862      }
 863  
 864      /**
 865       * Test we can read a competency with manage permissions.
 866       */
 867      public function test_read_competencies_with_manage_permissions_in_category() {
 868          $this->setUser($this->creator);
 869  
 870          $sysframework = $this->create_competency_framework(1, true);
 871          $insystem = $this->create_competency(1, $sysframework->id);
 872  
 873          $catframework = $this->create_competency_framework(2, false);
 874          $incat = $this->create_competency(2, $catframework->id);
 875  
 876          $this->setUser($this->catcreator);
 877          $id = $incat->id;
 878          $result = external::read_competency($id);
 879          $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
 880  
 881          $this->assertGreaterThan(0, $result->timecreated);
 882          $this->assertGreaterThan(0, $result->timemodified);
 883          $this->assertEquals($this->creator->id, $result->usermodified);
 884          $this->assertEquals('shortname2', $result->shortname);
 885          $this->assertEquals('idnumber2', $result->idnumber);
 886          $this->assertEquals('description2', $result->description);
 887          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 888          $this->assertEquals(0, $result->parentid);
 889          $this->assertEquals($catframework->id, $result->competencyframeworkid);
 890  
 891          try {
 892              external::read_competency($insystem->id);
 893              $this->fail('User should not be able to read a competency in system context.');
 894          } catch (required_capability_exception $e) {
 895              // All good.
 896          }
 897      }
 898  
 899      /**
 900       * Test we can read a competency with read permissions.
 901       */
 902      public function test_read_competencies_with_read_permissions() {
 903          $this->setUser($this->creator);
 904          $framework = $this->create_competency_framework(1, true);
 905          $competency = $this->create_competency(1, $framework->id);
 906  
 907          // Switch users to someone with less permissions.
 908          $this->setUser($this->user);
 909          $id = $competency->id;
 910          $result = external::read_competency($id);
 911          $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
 912  
 913          $this->assertGreaterThan(0, $result->timecreated);
 914          $this->assertGreaterThan(0, $result->timemodified);
 915          $this->assertEquals($this->creator->id, $result->usermodified);
 916          $this->assertEquals('shortname1', $result->shortname);
 917          $this->assertEquals('idnumber1', $result->idnumber);
 918          $this->assertEquals('description1', $result->description);
 919          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 920          $this->assertEquals(0, $result->parentid);
 921          $this->assertEquals($framework->id, $result->competencyframeworkid);
 922      }
 923  
 924      /**
 925       * Test we can read a competency with read permissions.
 926       */
 927      public function test_read_competencies_with_read_permissions_in_category() {
 928          $this->setUser($this->creator);
 929          $sysframework = $this->create_competency_framework(1, true);
 930          $insystem = $this->create_competency(1, $sysframework->id);
 931          $catframework = $this->create_competency_framework(2, false);
 932          $incat = $this->create_competency(2, $catframework->id);
 933  
 934          // Switch users to someone with less permissions.
 935          $this->setUser($this->catuser);
 936          $id = $incat->id;
 937          $result = external::read_competency($id);
 938          $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result);
 939  
 940          $this->assertGreaterThan(0, $result->timecreated);
 941          $this->assertGreaterThan(0, $result->timemodified);
 942          $this->assertEquals($this->creator->id, $result->usermodified);
 943          $this->assertEquals('shortname2', $result->shortname);
 944          $this->assertEquals('idnumber2', $result->idnumber);
 945          $this->assertEquals('description2', $result->description);
 946          $this->assertEquals(FORMAT_HTML, $result->descriptionformat);
 947          $this->assertEquals(0, $result->parentid);
 948          $this->assertEquals($catframework->id, $result->competencyframeworkid);
 949  
 950          try {
 951              external::read_competency($insystem->id);
 952              $this->fail('User should not be able to read a competency in system context.');
 953          } catch (required_capability_exception $e) {
 954              // All good.
 955          }
 956      }
 957  
 958      /**
 959       * Test we can delete a competency with manage permissions.
 960       */
 961      public function test_delete_competency_with_manage_permissions() {
 962          $this->setUser($this->creator);
 963          $framework = $this->create_competency_framework(1, true);
 964          $result = $this->create_competency(1, $framework->id);
 965  
 966          $id = $result->id;
 967          $result = external::delete_competency($id);
 968          $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
 969  
 970          $this->assertTrue($result);
 971      }
 972  
 973      /**
 974       * Test we can delete a competency with manage permissions.
 975       */
 976      public function test_delete_competency_with_manage_permissions_in_category() {
 977          $this->setUser($this->creator);
 978  
 979          $sysframework = $this->create_competency_framework(1, true);
 980          $insystem = $this->create_competency(1, $sysframework->id);
 981          $catframework = $this->create_competency_framework(2, false);
 982          $incat = $this->create_competency(2, $catframework->id);
 983  
 984          $this->setUser($this->catcreator);
 985          $id = $incat->id;
 986          $result = external::delete_competency($id);
 987          $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
 988  
 989          $this->assertTrue($result);
 990  
 991          try {
 992              $result = external::delete_competency($insystem->id);
 993              $this->fail('User should not be able to delete a competency in system context.');
 994          } catch (required_capability_exception $e) {
 995              // All good.
 996          }
 997      }
 998  
 999      /**
1000       * Test we can delete a competency with read permissions.
1001       *
1002       * @expectedException required_capability_exception
1003       */
1004      public function test_delete_competency_with_read_permissions() {
1005          $this->setUser($this->creator);
1006          $framework = $this->create_competency_framework(1, true);
1007          $result = $this->create_competency(1, $framework->id);
1008  
1009          $id = $result->id;
1010          // Switch users to someone with less permissions.
1011          $this->setUser($this->user);
1012          $result = external::delete_competency($id);
1013      }
1014  
1015      /**
1016       * Test we can update a competency with manage permissions.
1017       */
1018      public function test_update_competency_with_manage_permissions() {
1019          $this->setUser($this->creator);
1020          $framework = $this->create_competency_framework(1, true);
1021          $result = $this->create_competency(1, $framework->id);
1022  
1023          $result = $this->update_competency($result->id, 2);
1024  
1025          $this->assertTrue($result);
1026      }
1027  
1028      /**
1029       * Test we can update a competency with manage permissions.
1030       */
1031      public function test_update_competency_with_manage_permissions_in_category() {
1032          $this->setUser($this->creator);
1033  
1034          $sysframework = $this->create_competency_framework(1, true);
1035          $insystem = $this->create_competency(1, $sysframework->id);
1036          $catframework = $this->create_competency_framework(2, false);
1037          $incat = $this->create_competency(2, $catframework->id);
1038  
1039          $this->setUser($this->catcreator);
1040  
1041          $result = $this->update_competency($incat->id, 2);
1042  
1043          $this->assertTrue($result);
1044  
1045          try {
1046              $result = $this->update_competency($insystem->id, 3);
1047              $this->fail('User should not be able to update a competency in system context.');
1048          } catch (required_capability_exception $e) {
1049              // All good.
1050          }
1051      }
1052  
1053      /**
1054       * Test we can update a competency with read permissions.
1055       *
1056       * @expectedException required_capability_exception
1057       */
1058      public function test_update_competency_with_read_permissions() {
1059          $this->setUser($this->creator);
1060          $framework = $this->create_competency_framework(1, true);
1061          $result = $this->create_competency(1, $framework->id);
1062  
1063          $this->setUser($this->user);
1064          $result = $this->update_competency($result->id, 2);
1065      }
1066  
1067      /**
1068       * Test count competencies with filters.
1069       */
1070      public function test_count_competencies_with_filters() {
1071          $this->setUser($this->creator);
1072  
1073          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1074          $f1 = $lpg->create_framework();
1075          $f2 = $lpg->create_framework();
1076          $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
1077          $c2 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id'), 'shortname' => 'A'));
1078          $c3 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
1079          $c4 = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
1080          $c5 = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
1081  
1082          $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f2->get('id'))));
1083          $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1084          $this->assertEquals(2, $result);
1085  
1086          $result = external::count_competencies(array(array('column' => 'competencyframeworkid', 'value' => $f1->get('id'))));
1087          $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1088          $this->assertEquals(3, $result);
1089  
1090          $result = external::count_competencies(array(array('column' => 'shortname', 'value' => 'A')));
1091          $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1092          $this->assertEquals(1, $result);
1093      }
1094  
1095      /**
1096       * Test we can list and count competencies with manage permissions.
1097       */
1098      public function test_list_and_count_competencies_with_manage_permissions() {
1099          $this->setUser($this->creator);
1100          $framework = $this->create_competency_framework(1, true);
1101          $result = $this->create_competency(1, $framework->id);
1102          $result = $this->create_competency(2, $framework->id);
1103          $result = $this->create_competency(3, $framework->id);
1104  
1105          $result = external::count_competencies(array());
1106          $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1107  
1108          $this->assertEquals($result, 3);
1109  
1110          array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1111          $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1112  
1113          $this->assertEquals(count($result), 3);
1114          $result = (object) $result[0];
1115  
1116          $this->assertGreaterThan(0, $result->timecreated);
1117          $this->assertGreaterThan(0, $result->timemodified);
1118          $this->assertEquals($this->creator->id, $result->usermodified);
1119          $this->assertEquals('shortname1', $result->shortname);
1120          $this->assertEquals('idnumber1', $result->idnumber);
1121          $this->assertEquals('description1', $result->description);
1122      }
1123  
1124      /**
1125       * Test we can list and count competencies with read permissions.
1126       */
1127      public function test_list_and_count_competencies_with_read_permissions() {
1128          $this->setUser($this->creator);
1129          $framework = $this->create_competency_framework(1, true);
1130          $result = $this->create_competency(1, $framework->id);
1131          $result = $this->create_competency(2, $framework->id);
1132          $result = $this->create_competency(3, $framework->id);
1133  
1134          $this->setUser($this->user);
1135  
1136          $result = external::count_competencies(array());
1137          $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result);
1138  
1139          $this->assertEquals($result, 3);
1140  
1141          array('id' => $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10, context_system::instance()->id));
1142          $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result);
1143  
1144          $this->assertEquals(count($result), 3);
1145          $result = (object) $result[0];
1146  
1147          $this->assertGreaterThan(0, $result->timecreated);
1148          $this->assertGreaterThan(0, $result->timemodified);
1149          $this->assertEquals($this->creator->id, $result->usermodified);
1150          $this->assertEquals('shortname1', $result->shortname);
1151          $this->assertEquals('idnumber1', $result->idnumber);
1152          $this->assertEquals('description1', $result->description);
1153      }
1154  
1155      /**
1156       * Test we can search for competencies.
1157       */
1158      public function test_search_competencies_with_read_permissions() {
1159          $this->setUser($this->creator);
1160          $framework = $this->create_competency_framework(1, true);
1161          $result = $this->create_competency(1, $framework->id);
1162          $result = $this->create_competency(2, $framework->id);
1163          $result = $this->create_competency(3, $framework->id);
1164  
1165          $this->setUser($this->user);
1166  
1167          $result = external::search_competencies('short', $framework->id);
1168          $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
1169  
1170          $this->assertEquals(count($result), 3);
1171          $result = (object) $result[0];
1172  
1173          $this->assertGreaterThan(0, $result->timecreated);
1174          $this->assertGreaterThan(0, $result->timemodified);
1175          $this->assertEquals($this->creator->id, $result->usermodified);
1176          $this->assertEquals('shortname1', $result->shortname);
1177          $this->assertEquals('idnumber1', $result->idnumber);
1178          $this->assertEquals('description1', $result->description);
1179      }
1180  
1181      /**
1182       * Test plans creation and updates.
1183       */
1184      public function test_create_and_update_plans() {
1185          $syscontext = context_system::instance();
1186  
1187          $this->setUser($this->creator);
1188          $plan0 = $this->create_plan(1, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1189  
1190          $this->setUser($this->user);
1191  
1192          try {
1193              $plan1 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1194              $this->fail('Exception expected due to not permissions to create draft plans');
1195          } catch (moodle_exception $e) {
1196              $this->assertEquals('nopermissions', $e->errorcode);
1197          }
1198  
1199          assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1200          accesslib_clear_all_caches_for_unit_testing();
1201  
1202          $this->setUser($this->user);
1203  
1204          $plan2 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1205  
1206          // Basic update on the plan.
1207          $this->assertNotEquals('Updated plan 2 name', $plan2->name);
1208          $plan2 = external::update_plan(['id' => $plan2->id, 'name' => 'Updated plan 2 name']);
1209          $this->assertEquals('Updated plan 2 name', $plan2->name);
1210  
1211          try {
1212              $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1213              $this->fail('Exception expected due to not permissions to create active plans');
1214          } catch (moodle_exception $e) {
1215              $this->assertEquals('nopermissions', $e->errorcode);
1216          }
1217          try {
1218              $plan3 = $this->update_plan($plan2->id, 4, $this->user->id, 0, plan::STATUS_COMPLETE, 0);
1219              $this->fail('We cannot complete a plan using api::update_plan().');
1220          } catch (coding_exception $e) {
1221              $this->assertTrue(true);
1222          }
1223  
1224          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1225          accesslib_clear_all_caches_for_unit_testing();
1226  
1227          $plan3 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1228          try {
1229              $plan4 = $this->create_plan(6, $this->creator->id, 0, plan::STATUS_COMPLETE, 0);
1230              $this->fail('Plans cannot be created as complete.');
1231          } catch (coding_exception $e) {
1232              $this->assertRegexp('/A plan cannot be created as complete./', $e->getMessage());
1233          }
1234  
1235          try {
1236              $plan0 = $this->update_plan($plan0->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1237          } catch (moodle_exception $e) {
1238              $this->assertEquals('nopermissions', $e->errorcode);
1239          }
1240  
1241          unassign_capability('moodle/competency:planmanageown', $this->userrole, $syscontext->id);
1242          unassign_capability('moodle/competency:planmanageowndraft', $this->userrole, $syscontext->id);
1243          accesslib_clear_all_caches_for_unit_testing();
1244  
1245          try {
1246              // Cannot be updated even if they created it.
1247              $this->update_plan($plan2->id, 1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1248              $this->fail('The user can not update their own plan without permissions.');
1249          } catch (required_capability_exception $e) {
1250              $this->assertRegexp('/Manage learning plans./', $e->getMessage());
1251          }
1252      }
1253  
1254      /**
1255       * Test complete plan.
1256       */
1257      public function test_complete_plan() {
1258          $syscontext = context_system::instance();
1259  
1260          $this->setUser($this->creator);
1261  
1262          $this->setUser($this->user);
1263  
1264          assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1265          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1266          accesslib_clear_all_caches_for_unit_testing();
1267  
1268          $this->setUser($this->user);
1269  
1270          $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1271  
1272          $result = external::complete_plan($plan->id);
1273          $this->assertTrue($result);
1274      }
1275  
1276      /**
1277       * Test reopen plan.
1278       */
1279      public function test_reopen_plan() {
1280          $syscontext = context_system::instance();
1281  
1282          $this->setUser($this->creator);
1283  
1284          $this->setUser($this->user);
1285  
1286          assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id);
1287          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1288          accesslib_clear_all_caches_for_unit_testing();
1289  
1290          $this->setUser($this->user);
1291  
1292          $plan = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1293          external::complete_plan($plan->id);
1294  
1295          $result = external::reopen_plan($plan->id);
1296          $this->assertTrue($result);
1297      }
1298  
1299      /**
1300       * Test that we can read plans.
1301       */
1302      public function test_read_plans() {
1303          global $OUTPUT;
1304          $this->setUser($this->creator);
1305  
1306          $syscontext = context_system::instance();
1307  
1308          $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_DRAFT, 0);
1309          $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1310          $plan3 = $this->create_plan(3, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1311          external::complete_plan($plan3->id);
1312          $plan3 = (object) external::read_plan($plan3->id);
1313  
1314          $data = external::read_plan($plan1->id);
1315          $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1316          $data = external::read_plan($plan2->id);
1317          $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1318          $data = external::read_plan($plan3->id);
1319          $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1320  
1321          $this->setUser($this->user);
1322  
1323          // The normal user can not edit these plans.
1324          $plan1->canmanage = false;
1325          $plan2->canmanage = false;
1326          $plan3->canmanage = false;
1327          $plan1->canbeedited = false;
1328          $plan2->canbeedited = false;
1329          $plan3->canbeedited = false;
1330          $plan1->canrequestreview = true;
1331          $plan2->canrequestreview = true;
1332          $plan3->canrequestreview = true;
1333          $plan1->canreview = false;
1334          $plan2->canreview = false;
1335          $plan3->canreview = false;
1336          $plan1->iscompleteallowed = false;
1337          $plan2->iscompleteallowed = false;
1338          $plan3->iscompleteallowed = false;
1339          $plan1->isrequestreviewallowed = true;
1340          $plan2->isrequestreviewallowed = true;
1341          $plan3->isrequestreviewallowed = true;
1342          $plan1->isapproveallowed = false;
1343          $plan2->isapproveallowed = false;
1344          $plan3->isapproveallowed = false;
1345          $plan1->isunapproveallowed = false;
1346          $plan2->isunapproveallowed = false;
1347          $plan3->isunapproveallowed = false;
1348          $plan3->isreopenallowed = false;
1349          $plan1->commentarea['canpost'] = false;
1350          $plan1->commentarea['canview'] = true;
1351  
1352          // Prevent the user from seeing their own non-draft plans.
1353          assign_capability('moodle/competency:plancommentown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1354          assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1355          assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1356          accesslib_clear_all_caches_for_unit_testing();
1357  
1358          $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1359  
1360          try {
1361              external::read_plan($plan2->id);
1362              $this->fail('Exception expected due to not permissions to read plan');
1363          } catch (moodle_exception $e) {
1364              $this->assertEquals('nopermissions', $e->errorcode);
1365          }
1366          try {
1367              external::read_plan($plan3->id);
1368              $this->fail('Exception expected due to not permissions to read plan');
1369          } catch (moodle_exception $e) {
1370              $this->assertEquals('nopermissions', $e->errorcode);
1371          }
1372  
1373          // Allow user to see their plan.
1374          assign_capability('moodle/competency:plancommentown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1375          assign_capability('moodle/competency:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1376          assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1377          accesslib_clear_all_caches_for_unit_testing();
1378  
1379          $plan1->commentarea['canpost'] = true;
1380          $plan1->commentarea['canview'] = true;
1381          $plan2->commentarea['canpost'] = true;
1382          $plan2->isrequestreviewallowed = false;
1383          $plan3->commentarea['canpost'] = true;
1384          $plan3->isrequestreviewallowed = false;
1385          $plan1->commentarea['canpostorhascomments'] = true;
1386          $plan2->commentarea['canpostorhascomments'] = true;
1387          $plan3->commentarea['canpostorhascomments'] = true;
1388  
1389          $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1390          $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1391          $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1392  
1393          // Allow use to manage their own draft plan.
1394          assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1395          assign_capability('moodle/competency:planmanageown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1396          assign_capability('moodle/competency:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1397          accesslib_clear_all_caches_for_unit_testing();
1398  
1399          $plan1->canmanage = true;
1400          $plan1->canbeedited = true;
1401          $plan1->canrequestreview = true;
1402          $plan1->isrequestreviewallowed = true;
1403          $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1404          try {
1405              external::read_plan($plan2->id);
1406              $this->fail('Exception expected due to not permissions to read plan');
1407          } catch (moodle_exception $e) {
1408              $this->assertEquals('nopermissions', $e->errorcode);
1409          }
1410          try {
1411              external::read_plan($plan3->id);
1412              $this->fail('Exception expected due to not permissions to read plan');
1413          } catch (moodle_exception $e) {
1414              $this->assertEquals('nopermissions', $e->errorcode);
1415          }
1416  
1417          // Allow use to manage their plan.
1418          assign_capability('moodle/competency:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1419          assign_capability('moodle/competency:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true);
1420          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id, true);
1421          accesslib_clear_all_caches_for_unit_testing();
1422  
1423          $plan1->canmanage = false;
1424          $plan1->canbeedited = false;
1425          $plan1->canrequestreview = true;
1426          $plan1->canreview = true;
1427          $plan1->isrequestreviewallowed = true;
1428          $plan1->isapproveallowed = true;
1429          $plan1->iscompleteallowed = false;
1430  
1431          $plan2->canmanage = true;
1432          $plan2->canbeedited = true;
1433          $plan2->canreview = true;
1434          $plan2->iscompleteallowed = true;
1435          $plan2->isunapproveallowed = true;
1436  
1437          $plan3->canmanage = true;
1438          $plan3->canreview = true;
1439          $plan3->isreopenallowed = true;
1440  
1441          $this->assertEquals((array)$plan1, external::read_plan($plan1->id));
1442          $this->assertEquals((array)$plan2, external::read_plan($plan2->id));
1443          $this->assertEquals((array)$plan3, external::read_plan($plan3->id));
1444      }
1445  
1446      public function test_delete_plans() {
1447          $this->setUser($this->creator);
1448  
1449          $syscontext = context_system::instance();
1450  
1451          $plan1 = $this->create_plan(1, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1452          $plan2 = $this->create_plan(2, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1453          $plan3 = $this->create_plan(3, $this->creator->id, 0, plan::STATUS_ACTIVE, 0);
1454  
1455          $this->assertTrue(external::delete_plan($plan1->id));
1456  
1457          unassign_capability('moodle/competency:planmanage', $this->creatorrole, $syscontext->id);
1458          accesslib_clear_all_caches_for_unit_testing();
1459  
1460          try {
1461              external::delete_plan($plan2->id);
1462              $this->fail('Exception expected due to not permissions to manage plans');
1463          } catch (moodle_exception $e) {
1464              $this->assertEquals('nopermissions', $e->errorcode);
1465          }
1466  
1467          $this->setUser($this->user);
1468  
1469          // Can not delete plans created by other users.
1470          try {
1471              external::delete_plan($plan2->id);
1472              $this->fail('Exception expected due to not permissions to manage plans');
1473          } catch (moodle_exception $e) {
1474              $this->assertEquals('nopermissions', $e->errorcode);
1475          }
1476  
1477          assign_capability('moodle/competency:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id);
1478          accesslib_clear_all_caches_for_unit_testing();
1479  
1480          $this->assertTrue(external::delete_plan($plan2->id));
1481  
1482          // Can not delete plans created for other users.
1483          try {
1484              external::delete_plan($plan3->id);
1485              $this->fail('Exception expected due to not permissions to manage plans');
1486          } catch (moodle_exception $e) {
1487              $this->assertEquals('nopermissions', $e->errorcode);
1488          }
1489  
1490          $plan4 = $this->create_plan(4, $this->user->id, 0, plan::STATUS_ACTIVE, 0);
1491          $this->assertTrue(external::delete_plan($plan4->id));
1492      }
1493  
1494      public function test_delete_plan_removes_relations() {
1495          $this->setAdminUser();
1496          $dg = $this->getDataGenerator();
1497          $lpg = $dg->get_plugin_generator('core_competency');
1498  
1499          $user = $dg->create_user();
1500          $plan = $lpg->create_plan(array('userid' => $user->id));
1501          $framework = $lpg->create_framework();
1502          $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1503          $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1504          $comp3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1505          $pc1 = $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $comp1->get('id')));
1506          $pc2 = $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $comp2->get('id')));
1507          $pc3 = $lpg->create_plan_competency(array('planid' => $plan->get('id'), 'competencyid' => $comp3->get('id')));
1508  
1509          // Complete the plan to generate user_competency_plan entries.
1510          api::complete_plan($plan);
1511  
1512          // Confirm the data we have.
1513          $this->assertEquals(3, plan_competency::count_records(array('planid' => $plan->get('id'))));
1514          $this->assertEquals(3, user_competency_plan::count_records(array('planid' => $plan->get('id'), 'userid' => $user->id)));
1515  
1516          // Delete the plan now.
1517          api::delete_plan($plan->get('id'));
1518          $this->assertEquals(0, plan_competency::count_records(array('planid' => $plan->get('id'))));
1519          $this->assertEquals(0, user_competency_plan::count_records(array('planid' => $plan->get('id'), 'userid' => $user->id)));
1520      }
1521  
1522      public function test_list_plan_competencies() {
1523          $this->setUser($this->creator);
1524  
1525          $dg = $this->getDataGenerator();
1526          $lpg = $dg->get_plugin_generator('core_competency');
1527  
1528          $f1 = $lpg->create_framework();
1529          $f2 = $lpg->create_framework();
1530  
1531          $c1a = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
1532          $c1b = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
1533          $c1c = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
1534          $c2a = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
1535          $c2b = $lpg->create_competency(array('competencyframeworkid' => $f2->get('id')));
1536  
1537          $tpl = $lpg->create_template();
1538          $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1a->get('id')));
1539          $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1c->get('id')));
1540          $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c2b->get('id')));
1541  
1542          $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get('id')));
1543  
1544          $uc1a = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1a->get('id'),
1545              'status' => user_competency::STATUS_IN_REVIEW, 'reviewerid' => $this->creator->id));
1546          $uc1b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1b->get('id')));
1547          $uc2b = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c2b->get('id'),
1548              'grade' => 2, 'proficiency' => 1));
1549          $ux1a = $lpg->create_user_competency(array('userid' => $this->creator->id, 'competencyid' => $c1a->get('id')));
1550  
1551          $result = external::list_plan_competencies($plan->get('id'));
1552          $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1553  
1554          $this->assertCount(3, $result);
1555          $this->assertEquals($c1a->get('id'), $result[0]['competency']['id']);
1556          $this->assertEquals($this->user->id, $result[0]['usercompetency']['userid']);
1557          $this->assertArrayNotHasKey('usercompetencyplan', $result[0]);
1558          $this->assertEquals($c1c->get('id'), $result[1]['competency']['id']);
1559          $this->assertEquals($this->user->id, $result[1]['usercompetency']['userid']);
1560          $this->assertArrayNotHasKey('usercompetencyplan', $result[1]);
1561          $this->assertEquals($c2b->get('id'), $result[2]['competency']['id']);
1562          $this->assertEquals($this->user->id, $result[2]['usercompetency']['userid']);
1563          $this->assertArrayNotHasKey('usercompetencyplan', $result[2]);
1564          $this->assertEquals(user_competency::STATUS_IN_REVIEW, $result[0]['usercompetency']['status']);
1565          $this->assertEquals(null, $result[1]['usercompetency']['grade']);
1566          $this->assertEquals(2, $result[2]['usercompetency']['grade']);
1567          $this->assertEquals(1, $result[2]['usercompetency']['proficiency']);
1568  
1569          // Check the return values when the plan status is complete.
1570          $completedplan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get('id'),
1571                  'status' => plan::STATUS_COMPLETE));
1572  
1573          $uc1a = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1a->get('id'),
1574                  'planid' => $completedplan->get('id')));
1575          $uc1b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c1c->get('id'),
1576                  'planid' => $completedplan->get('id')));
1577          $uc2b = $lpg->create_user_competency_plan(array('userid' => $this->user->id, 'competencyid' => $c2b->get('id'),
1578                  'planid' => $completedplan->get('id'), 'grade' => 2, 'proficiency' => 1));
1579          $ux1a = $lpg->create_user_competency_plan(array('userid' => $this->creator->id, 'competencyid' => $c1a->get('id'),
1580                  'planid' => $completedplan->get('id')));
1581  
1582          $result = external::list_plan_competencies($completedplan->get('id'));
1583          $result = external::clean_returnvalue(external::list_plan_competencies_returns(), $result);
1584  
1585          $this->assertCount(3, $result);
1586          $this->assertEquals($c1a->get('id'), $result[0]['competency']['id']);
1587          $this->assertEquals($this->user->id, $result[0]['usercompetencyplan']['userid']);
1588          $this->assertArrayNotHasKey('usercompetency', $result[0]);
1589          $this->assertEquals($c1c->get('id'), $result[1]['competency']['id']);
1590          $this->assertEquals($this->user->id, $result[1]['usercompetencyplan']['userid']);
1591          $this->assertArrayNotHasKey('usercompetency', $result[1]);
1592          $this->assertEquals($c2b->get('id'), $result[2]['competency']['id']);
1593          $this->assertEquals($this->user->id, $result[2]['usercompetencyplan']['userid']);
1594          $this->assertArrayNotHasKey('usercompetency', $result[2]);
1595          $this->assertEquals(null, $result[1]['usercompetencyplan']['grade']);
1596          $this->assertEquals(2, $result[2]['usercompetencyplan']['grade']);
1597          $this->assertEquals(1, $result[2]['usercompetencyplan']['proficiency']);
1598      }
1599  
1600      public function test_add_competency_to_template() {
1601          $this->setUser($this->creator);
1602  
1603          $syscontext = context_system::instance();
1604  
1605          // Create a template.
1606          $template = $this->create_template(1, true);
1607  
1608          // Create a competency.
1609          $framework = $this->create_competency_framework(1, true);
1610          $competency = $this->create_competency(1, $framework->id);
1611  
1612          // Add the competency.
1613          external::add_competency_to_template($template->id, $competency->id);
1614  
1615          // Check that it was added.
1616          $this->assertEquals(1, external::count_competencies_in_template($template->id));
1617  
1618          // Unassign capability.
1619          unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1620          accesslib_clear_all_caches_for_unit_testing();
1621  
1622          // Check we can not add the competency now.
1623          try {
1624              external::add_competency_to_template($template->id, $competency->id);
1625              $this->fail('Exception expected due to not permissions to manage template competencies');
1626          } catch (moodle_exception $e) {
1627              $this->assertEquals('nopermissions', $e->errorcode);
1628          }
1629      }
1630  
1631      public function test_remove_competency_from_template() {
1632          $syscontext = context_system::instance();
1633          $this->setUser($this->creator);
1634          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
1635  
1636          // Create a template.
1637          $template = $this->create_template(1, true);
1638  
1639          // Create a competency.
1640          $framework = $lpg->create_framework();
1641          $competency = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
1642  
1643          // Add the competency.
1644          external::add_competency_to_template($template->id, $competency->get('id'));
1645  
1646          // Check that it was added.
1647          $this->assertEquals(1, external::count_competencies_in_template($template->id));
1648  
1649          // Check that we can remove the competency.
1650          external::remove_competency_from_template($template->id, $competency->get('id'));
1651  
1652          // Check that it was removed.
1653          $this->assertEquals(0, external::count_competencies_in_template($template->id));
1654  
1655          // Unassign capability.
1656          unassign_capability('moodle/competency:templatemanage', $this->creatorrole, $syscontext->id);
1657          accesslib_clear_all_caches_for_unit_testing();
1658  
1659          // Check we can not remove the competency now.
1660          try {
1661              external::add_competency_to_template($template->id, $competency->get('id'));
1662              $this->fail('Exception expected due to not permissions to manage template competencies');
1663          } catch (moodle_exception $e) {
1664              $this->assertEquals('nopermissions', $e->errorcode);
1665          }
1666      }
1667  
1668      /**
1669       * Test we can re-order competency frameworks.
1670       */
1671      public function test_reorder_template_competencies() {
1672          $this->setUser($this->creator);
1673  
1674          $syscontext = context_system::instance();
1675          $onehour = time() + 60 * 60;
1676  
1677          // Create a template.
1678          $template = $this->create_template(1, true);
1679  
1680          // Create a competency framework.
1681          $framework = $this->create_competency_framework(1, true);
1682  
1683          // Create multiple competencies.
1684          $competency1 = $this->create_competency(1, $framework->id);
1685          $competency2 = $this->create_competency(2, $framework->id);
1686          $competency3 = $this->create_competency(3, $framework->id);
1687          $competency4 = $this->create_competency(4, $framework->id);
1688  
1689          // Add the competencies.
1690          external::add_competency_to_template($template->id, $competency1->id);
1691          external::add_competency_to_template($template->id, $competency2->id);
1692          external::add_competency_to_template($template->id, $competency3->id);
1693          external::add_competency_to_template($template->id, $competency4->id);
1694  
1695          // Test if removing competency from template don't create sortorder holes.
1696          external::remove_competency_from_template($template->id, $competency3->id);
1697          $templcomp4 = template_competency::get_record(array(
1698              'templateid' => $template->id,
1699              'competencyid' => $competency4->id
1700          ));
1701  
1702          $this->assertEquals(2, $templcomp4->get('sortorder'));
1703  
1704          // This is a move up.
1705          external::reorder_template_competency($template->id, $competency4->id, $competency2->id);
1706          $result = external::list_competencies_in_template($template->id);
1707          $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1708  
1709          $r1 = (object) $result[0];
1710          $r2 = (object) $result[1];
1711          $r3 = (object) $result[2];
1712  
1713          $this->assertEquals($competency1->id, $r1->id);
1714          $this->assertEquals($competency4->id, $r2->id);
1715          $this->assertEquals($competency2->id, $r3->id);
1716  
1717          // This is a move down.
1718          external::reorder_template_competency($template->id, $competency1->id, $competency4->id);
1719          $result = external::list_competencies_in_template($template->id);
1720          $result = external_api::clean_returnvalue(external::list_competencies_in_template_returns(), $result);
1721  
1722          $r1 = (object) $result[0];
1723          $r2 = (object) $result[1];
1724          $r3 = (object) $result[2];
1725  
1726          $this->assertEquals($competency4->id, $r1->id);
1727          $this->assertEquals($competency1->id, $r2->id);
1728          $this->assertEquals($competency2->id, $r3->id);
1729  
1730          $this->expectException('required_capability_exception');
1731          $this->setUser($this->user);
1732          external::reorder_template_competency($template->id, $competency1->id, $competency2->id);
1733      }
1734  
1735      /**
1736       * Test we can duplicate learning plan template.
1737       */
1738      public function test_duplicate_learning_plan_template() {
1739          $this->setUser($this->creator);
1740  
1741          $syscontext = context_system::instance();
1742          $onehour = time() + 60 * 60;
1743  
1744          // Create a template.
1745          $template = $this->create_template(1, true);
1746  
1747          // Create a competency framework.
1748          $framework = $this->create_competency_framework(1, true);
1749  
1750          // Create multiple competencies.
1751          $competency1 = $this->create_competency(1, $framework->id);
1752          $competency2 = $this->create_competency(2, $framework->id);
1753          $competency3 = $this->create_competency(3, $framework->id);
1754  
1755          // Add the competencies.
1756          external::add_competency_to_template($template->id, $competency1->id);
1757          external::add_competency_to_template($template->id, $competency2->id);
1758          external::add_competency_to_template($template->id, $competency3->id);
1759  
1760          // Duplicate the learning plan template.
1761          $duplicatedtemplate = external::duplicate_template($template->id);
1762  
1763          $result = external::list_competencies_in_template($template->id);
1764          $resultduplicated = external::list_competencies_in_template($duplicatedtemplate->id);
1765  
1766          $this->assertEquals(count($result), count($resultduplicated));
1767          $this->assertContains($template->shortname, $duplicatedtemplate->shortname);
1768          $this->assertEquals($duplicatedtemplate->description, $template->description);
1769          $this->assertEquals($duplicatedtemplate->descriptionformat, $template->descriptionformat);
1770          $this->assertEquals($duplicatedtemplate->visible, $template->visible);
1771      }
1772  
1773      /**
1774       * Test that we can return scale values for a scale with the scale ID.
1775       */
1776      public function test_get_scale_values() {
1777          global $DB;
1778  
1779          $this->setUser($this->creator);
1780  
1781          // Create a scale.
1782          $record = new stdClass();
1783          $record->courseid = 0;
1784          $record->userid = $this->creator->id;
1785          $record->name = 'Test scale';
1786          $record->scale = 'Poor, Not good, Okay, Fine, Excellent';
1787          $record->description = '<p>Test scale description.</p>';
1788          $record->descriptionformat = 1;
1789          $record->timemodified = time();
1790          $scaleid = $DB->insert_record('scale', $record);
1791          // Expected return value.
1792          $expected = array(array(
1793                  'id' => 1,
1794                  'name' => 'Poor'
1795              ), array(
1796                  'id' => 2,
1797                  'name' => 'Not good'
1798              ), array(
1799                  'id' => 3,
1800                  'name' => 'Okay'
1801              ), array(
1802                  'id' => 4,
1803                  'name' => 'Fine'
1804              ), array(
1805                  'id' => 5,
1806                  'name' => 'Excellent'
1807              )
1808          );
1809          // Call the webservice.
1810          $result = external::get_scale_values($scaleid);
1811          $this->assertEquals($expected, $result);
1812      }
1813  
1814      /**
1815       * Create a template.
1816       */
1817      public function test_create_template() {
1818          $syscontextid = context_system::instance()->id;
1819          $catcontextid = context_coursecat::instance($this->category->id)->id;
1820  
1821          // A user without permission.
1822          $this->setUser($this->user);
1823          try {
1824              $result = $this->create_template(1, true);
1825              $this->fail('Invalid permissions');
1826          } catch (required_capability_exception $e) {
1827              // All good.
1828          }
1829  
1830          // A user without permission in a category.
1831          $this->setUser($this->catuser);
1832          try {
1833              $result = $this->create_template(1, false);
1834              $this->fail('Invalid permissions');
1835          } catch (required_capability_exception $e) {
1836              // All good.
1837          }
1838  
1839          // A user with permissions in the system.
1840          $this->setUser($this->creator);
1841          $result = $this->create_template(1, true);
1842          $this->assertEquals('shortname1', $result->shortname);
1843          $this->assertEquals($syscontextid, $result->contextid);
1844          $this->assertNotEmpty($result->id);
1845  
1846          $result = $this->create_template(2, false);
1847          $this->assertEquals('shortname2', $result->shortname);
1848          $this->assertEquals($catcontextid, $result->contextid);
1849          $this->assertNotEmpty($result->id);
1850  
1851          // A user with permissions in the category.
1852          $this->setUser($this->catcreator);
1853          try {
1854              $result = $this->create_template(3, true);
1855              $this->fail('Invalid permissions');
1856          } catch (required_capability_exception $e) {
1857              // All good.
1858          }
1859  
1860          $result = $this->create_template(3, false);
1861          $this->assertEquals('shortname3', $result->shortname);
1862          $this->assertEquals($catcontextid, $result->contextid);
1863          $this->assertNotEmpty($result->id);
1864      }
1865  
1866      /**
1867       * Read a template.
1868       */
1869      public function test_read_template() {
1870          $syscontextid = context_system::instance()->id;
1871          $catcontextid = context_coursecat::instance($this->category->id)->id;
1872  
1873          // Set a due date for the next year.
1874          $date = new DateTime('now');
1875          $date->modify('+1 year');
1876          $duedate = $date->getTimestamp();
1877  
1878          // Creating two templates.
1879          $this->setUser($this->creator);
1880          $systemplate = $this->create_template(1, true);
1881          $cattemplate = $this->create_template(2, false);
1882  
1883          // User without permissions to read in system.
1884          assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
1885          accesslib_clear_all_caches_for_unit_testing();
1886          $this->setUser($this->user);
1887          $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1888          try {
1889              external::read_template($systemplate->id);
1890              $this->fail('Invalid permissions');
1891          } catch (required_capability_exception $e) {
1892              // All good.
1893          }
1894          try {
1895              external::read_template($cattemplate->id);
1896              $this->fail('Invalid permissions');
1897          } catch (required_capability_exception $e) {
1898              // All good.
1899          }
1900  
1901          // User with permissions to read in a category.
1902          assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
1903          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
1904          accesslib_clear_all_caches_for_unit_testing();
1905          $this->assertFalse(has_capability('moodle/competency:templateview', context_system::instance()));
1906          $this->assertTrue(has_capability('moodle/competency:templateview', context_coursecat::instance($this->category->id)));
1907          try {
1908              external::read_template($systemplate->id);
1909              $this->fail('Invalid permissions');
1910          } catch (required_capability_exception $e) {
1911              // All good.
1912          }
1913  
1914          $result = external::read_template($cattemplate->id);
1915          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1916          $this->assertEquals($cattemplate->id, $result['id']);
1917          $this->assertEquals('shortname2', $result['shortname']);
1918          $this->assertEquals('description2', $result['description']);
1919          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1920          $this->assertEquals(1, $result['visible']);
1921          $this->assertEquals(0, $result['duedate']);
1922          $this->assertEquals(userdate(0), $result['duedateformatted']);
1923  
1924          // User with permissions to read in the system.
1925          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
1926          accesslib_clear_all_caches_for_unit_testing();
1927          $this->assertTrue(has_capability('moodle/competency:templateview', context_system::instance()));
1928          $result = external::read_template($systemplate->id);
1929          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1930          $this->assertEquals($systemplate->id, $result['id']);
1931          $this->assertEquals('shortname1', $result['shortname']);
1932          $this->assertEquals('description1', $result['description']);
1933          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1934          $this->assertEquals(true, $result['visible']);
1935          $this->assertEquals(0, $result['duedate']);
1936          $this->assertEquals(userdate(0), $result['duedateformatted']);
1937  
1938          $result = external::read_template($cattemplate->id);
1939          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1940          $this->assertEquals($cattemplate->id, $result['id']);
1941          $this->assertEquals('shortname2', $result['shortname']);
1942          $this->assertEquals('description2', $result['description']);
1943          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1944          $this->assertEquals(true, $result['visible']);
1945          $this->assertEquals(0, $result['duedate']);
1946          $this->assertEquals(userdate(0), $result['duedateformatted']);
1947      }
1948  
1949      /**
1950       * Update a template.
1951       */
1952      public function test_update_template() {
1953          $syscontextid = context_system::instance()->id;
1954          $catcontextid = context_coursecat::instance($this->category->id)->id;
1955  
1956          // Set a due date for the next year.
1957          $date = new DateTime('now');
1958          $date->modify('+1 year');
1959          $duedate = $date->getTimestamp();
1960  
1961          // Creating two templates.
1962          $this->setUser($this->creator);
1963          $systemplate = $this->create_template(1, true);
1964          $cattemplate = $this->create_template(2, false);
1965  
1966          // Trying to update in a without permissions.
1967          $this->setUser($this->user);
1968          try {
1969              $this->update_template($systemplate->id, 3);
1970              $this->fail('Invalid permissions');
1971          } catch (required_capability_exception $e) {
1972              // All good.
1973          }
1974  
1975          try {
1976              $this->update_template($cattemplate->id, 3);
1977              $this->fail('Invalid permissions');
1978          } catch (required_capability_exception $e) {
1979              // All good.
1980          }
1981  
1982          // User with permissions to update in category.
1983          $this->setUser($this->catcreator);
1984          try {
1985              $this->update_template($systemplate->id, 3);
1986              $this->fail('Invalid permissions');
1987          } catch (required_capability_exception $e) {
1988              // All good.
1989          }
1990  
1991          $result = $this->update_template($cattemplate->id, 3);
1992          $this->assertTrue($result);
1993          $result = external::read_template($cattemplate->id);
1994          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
1995          $this->assertEquals($cattemplate->id, $result['id']);
1996          $this->assertEquals('shortname3', $result['shortname']);
1997          $this->assertEquals("description3", $result['description']);
1998          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
1999          $this->assertEquals(true, $result['visible']);
2000          $this->assertEquals(0, $result['duedate']);
2001          $this->assertEquals(userdate(0), $result['duedateformatted']);
2002  
2003          // User with permissions to update in the system.
2004          $this->setUser($this->creator);
2005          $result = $this->update_template($systemplate->id, 4);
2006          $this->assertTrue($result);
2007          $result = external::read_template($systemplate->id);
2008          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
2009          $this->assertEquals($systemplate->id, $result['id']);
2010          $this->assertEquals('shortname4', $result['shortname']);
2011          $this->assertEquals('description4', $result['description']);
2012          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
2013          $this->assertEquals(true, $result['visible']);
2014          $this->assertEquals(0, $result['duedate']);
2015          $this->assertEquals(userdate(0), $result['duedateformatted']);
2016  
2017          $result = $this->update_template($cattemplate->id, 5);
2018          $this->assertTrue($result);
2019          $result = external::read_template($cattemplate->id);
2020          $result = external_api::clean_returnvalue(external::read_template_returns(), $result);
2021          $this->assertEquals($cattemplate->id, $result['id']);
2022          $this->assertEquals('shortname5', $result['shortname']);
2023          $this->assertEquals('description5', $result['description']);
2024          $this->assertEquals(FORMAT_HTML, $result['descriptionformat']);
2025          $this->assertEquals(1, $result['visible']);
2026          $this->assertEquals(0, $result['duedate']);
2027          $this->assertEquals(userdate(0), $result['duedateformatted']);
2028      }
2029  
2030      /**
2031       * Delete a template.
2032       */
2033      public function test_delete_template() {
2034          global $DB;
2035          $syscontextid = context_system::instance()->id;
2036          $catcontextid = context_coursecat::instance($this->category->id)->id;
2037  
2038          // Creating a few templates.
2039          $this->setUser($this->creator);
2040          $sys1 = $this->create_template(1, true);
2041          $cat1 = $this->create_template(2, false);
2042          $cat2 = $this->create_template(3, false);
2043          $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2044          $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2045          $this->assertTrue($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2046  
2047          // User without permissions.
2048          $this->setUser($this->user);
2049          try {
2050              external::delete_template($sys1->id);
2051              $this->fail('Invalid permissions');
2052          } catch (required_capability_exception $e) {
2053              // All good.
2054          }
2055          try {
2056              external::delete_template($cat1->id);
2057              $this->fail('Invalid permissions');
2058          } catch (required_capability_exception $e) {
2059              // All good.
2060          }
2061  
2062          // User with category permissions.
2063          $this->setUser($this->catcreator);
2064          try {
2065              external::delete_template($sys1->id);
2066              $this->fail('Invalid permissions');
2067          } catch (required_capability_exception $e) {
2068              // All good.
2069          }
2070  
2071          $result = external::delete_template($cat1->id);
2072          $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2073          $this->assertTrue($result);
2074          $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat1->id)));
2075  
2076          // User with system permissions.
2077          $this->setUser($this->creator);
2078          $result = external::delete_template($sys1->id);
2079          $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2080          $this->assertTrue($result);
2081          $result = external::delete_template($cat2->id);
2082          $result = external_api::clean_returnvalue(external::delete_template_returns(), $result);
2083          $this->assertTrue($result);
2084          $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $sys1->id)));
2085          $this->assertFalse($DB->record_exists(template::TABLE, array('id' => $cat2->id)));
2086      }
2087  
2088      /**
2089       * List templates.
2090       */
2091      public function test_list_templates() {
2092          $syscontextid = context_system::instance()->id;
2093          $catcontextid = context_coursecat::instance($this->category->id)->id;
2094  
2095          // Creating a few templates.
2096          $this->setUser($this->creator);
2097          $sys1 = $this->create_template(1, true);
2098          $sys2 = $this->create_template(2, true);
2099          $cat1 = $this->create_template(3, false);
2100          $cat2 = $this->create_template(4, false);
2101  
2102          // User without permission.
2103          $this->setUser($this->user);
2104          assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2105          accesslib_clear_all_caches_for_unit_testing();
2106          try {
2107              external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2108              $this->fail('Invalid permissions');
2109          } catch (required_capability_exception $e) {
2110              // All good.
2111          }
2112  
2113          // User with category permissions.
2114          assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2115          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2116          accesslib_clear_all_caches_for_unit_testing();
2117          $result = external::list_templates('id', 'ASC', 0, 10, array('contextid' => $syscontextid), 'children', false);
2118          $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2119          $this->assertCount(2, $result);
2120          $this->assertEquals($cat1->id, $result[0]['id']);
2121          $this->assertEquals($cat2->id, $result[1]['id']);
2122  
2123          // User with system permissions.
2124          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2125          accesslib_clear_all_caches_for_unit_testing();
2126          $result = external::list_templates('id', 'DESC', 0, 3, array('contextid' => $catcontextid), 'parents', false);
2127          $result = external_api::clean_returnvalue(external::list_templates_returns(), $result);
2128          $this->assertCount(3, $result);
2129          $this->assertEquals($cat2->id, $result[0]['id']);
2130          $this->assertEquals($cat1->id, $result[1]['id']);
2131          $this->assertEquals($sys2->id, $result[2]['id']);
2132      }
2133  
2134      /**
2135       * List templates using competency.
2136       */
2137      public function test_list_templates_using_competency() {
2138          $this->setUser($this->creator);
2139  
2140          // Create a template.
2141          $template1 = $this->create_template(1, true);
2142          $template2 = $this->create_template(2, true);
2143          $template3 = $this->create_template(3, true);
2144          $template4 = $this->create_template(4, true);
2145  
2146          // Create a competency.
2147          $framework = $this->create_competency_framework(1, true);
2148          $competency1 = $this->create_competency(1, $framework->id);
2149          $competency2 = $this->create_competency(2, $framework->id);
2150  
2151          // Add the competency.
2152          external::add_competency_to_template($template1->id, $competency1->id);
2153          external::add_competency_to_template($template2->id, $competency1->id);
2154          external::add_competency_to_template($template3->id, $competency1->id);
2155  
2156          external::add_competency_to_template($template4->id, $competency2->id);
2157  
2158          $listcomp1 = external::list_templates_using_competency($competency1->id);
2159          $listcomp2 = external::list_templates_using_competency($competency2->id);
2160  
2161          // Test count_templates_using_competency.
2162          $counttempcomp1 = external::count_templates_using_competency($competency1->id);
2163          $counttempcomp2 = external::count_templates_using_competency($competency2->id);
2164  
2165          $comptemp1 = $listcomp1[0];
2166          $comptemp2 = $listcomp1[1];
2167          $comptemp3 = $listcomp1[2];
2168  
2169          $comptemp4 = $listcomp2[0];
2170  
2171          $this->assertCount(3, $listcomp1);
2172          $this->assertCount(1, $listcomp2);
2173          $this->assertEquals(3, $counttempcomp1);
2174          $this->assertEquals(1, $counttempcomp2);
2175          $this->assertEquals($template1->id, $comptemp1->id);
2176          $this->assertEquals($template2->id, $comptemp2->id);
2177          $this->assertEquals($template3->id, $comptemp3->id);
2178          $this->assertEquals($template4->id, $comptemp4->id);
2179      }
2180  
2181      public function test_count_templates() {
2182          $syscontextid = context_system::instance()->id;
2183          $catcontextid = context_coursecat::instance($this->category->id)->id;
2184  
2185          // Creating a few templates.
2186          $this->setUser($this->creator);
2187          $sys1 = $this->create_template(1, true);
2188          $sys2 = $this->create_template(2, true);
2189          $cat1 = $this->create_template(3, false);
2190          $cat2 = $this->create_template(4, false);
2191          $cat3 = $this->create_template(5, false);
2192  
2193          // User without permission.
2194          $this->setUser($this->user);
2195          assign_capability('moodle/competency:templateview', CAP_PROHIBIT, $this->userrole, $syscontextid, true);
2196          accesslib_clear_all_caches_for_unit_testing();
2197          try {
2198              external::count_templates(array('contextid' => $syscontextid), 'children');
2199              $this->fail('Invalid permissions');
2200          } catch (required_capability_exception $e) {
2201              // All good.
2202          }
2203  
2204          // User with category permissions.
2205          assign_capability('moodle/competency:templateview', CAP_PREVENT, $this->userrole, $syscontextid, true);
2206          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $catcontextid, true);
2207          accesslib_clear_all_caches_for_unit_testing();
2208          $result = external::count_templates(array('contextid' => $syscontextid), 'children');
2209          $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2210          $this->assertEquals(3, $result);
2211  
2212          // User with system permissions.
2213          assign_capability('moodle/competency:templateview', CAP_ALLOW, $this->userrole, $syscontextid, true);
2214          accesslib_clear_all_caches_for_unit_testing();
2215          $result = external::count_templates(array('contextid' => $catcontextid), 'parents');
2216          $result = external_api::clean_returnvalue(external::count_templates_returns(), $result);
2217          $this->assertEquals(5, $result);
2218      }
2219  
2220      /**
2221       * Test that we can add related competencies.
2222       *
2223       * @return void
2224       */
2225      public function test_add_related_competency() {
2226          global $DB;
2227          $this->setUser($this->creator);
2228  
2229          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2230          $framework = $lpg->create_framework();
2231          $framework2 = $lpg->create_framework();
2232          $competency1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2233          $competency2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2234          $competency3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2235          $competency4 = $lpg->create_competency(array('competencyframeworkid' => $framework2->get('id')));
2236  
2237          // The lower one always as competencyid.
2238          $result = external::add_related_competency($competency1->get('id'), $competency2->get('id'));
2239          $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2240          $this->assertTrue($result);
2241          $this->assertTrue($DB->record_exists_select(
2242              related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2243              array(
2244                  'cid' => $competency1->get('id'),
2245                  'rid' => $competency2->get('id')
2246              )
2247          ));
2248          $this->assertFalse($DB->record_exists_select(
2249              related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2250              array(
2251                  'cid' => $competency2->get('id'),
2252                  'rid' => $competency1->get('id')
2253              )
2254          ));
2255  
2256          $result = external::add_related_competency($competency3->get('id'), $competency1->get('id'));
2257          $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2258          $this->assertTrue($result);
2259          $this->assertTrue($DB->record_exists_select(
2260              related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2261              array(
2262                  'cid' => $competency1->get('id'),
2263                  'rid' => $competency3->get('id')
2264              )
2265          ));
2266          $this->assertFalse($DB->record_exists_select(
2267              related_competency::TABLE, 'competencyid = :cid AND relatedcompetencyid = :rid',
2268              array(
2269                  'cid' => $competency3->get('id'),
2270                  'rid' => $competency1->get('id')
2271              )
2272          ));
2273  
2274          // We can not allow a duplicate relation, not even in the other direction.
2275          $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2276              'competencyid = :cid AND relatedcompetencyid = :rid',
2277              array('cid' => $competency1->get('id'), 'rid' => $competency2->get('id'))));
2278          $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2279              'competencyid = :cid AND relatedcompetencyid = :rid',
2280              array('rid' => $competency1->get('id'), 'cid' => $competency2->get('id'))));
2281          $result = external::add_related_competency($competency2->get('id'), $competency1->get('id'));
2282          $result = external_api::clean_returnvalue(external::add_related_competency_returns(), $result);
2283          $this->assertTrue($result);
2284          $this->assertEquals(1, $DB->count_records_select(related_competency::TABLE,
2285              'competencyid = :cid AND relatedcompetencyid = :rid',
2286              array('cid' => $competency1->get('id'), 'rid' => $competency2->get('id'))));
2287          $this->assertEquals(0, $DB->count_records_select(related_competency::TABLE,
2288              'competencyid = :cid AND relatedcompetencyid = :rid',
2289              array('rid' => $competency1->get('id'), 'cid' => $competency2->get('id'))));
2290  
2291          // Check that we cannot create links across frameworks.
2292          try {
2293              external::add_related_competency($competency1->get('id'), $competency4->get('id'));
2294              $this->fail('Exception expected due mis-use of shared competencies');
2295          } catch (invalid_persistent_exception $e) {
2296              // Yay!
2297          }
2298  
2299          // User without permission.
2300          $this->setUser($this->user);
2301  
2302          // Check we can not add the related competency now.
2303          try {
2304              external::add_related_competency($competency1->get('id'), $competency3->get('id'));
2305              $this->fail('Exception expected due to not permissions to manage template competencies');
2306          } catch (moodle_exception $e) {
2307              $this->assertEquals('nopermissions', $e->errorcode);
2308          }
2309  
2310      }
2311  
2312      /**
2313       * Test that we can remove related competencies.
2314       *
2315       * @return void
2316       */
2317      public function test_remove_related_competency() {
2318          $this->setUser($this->creator);
2319  
2320          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2321          $framework = $lpg->create_framework();
2322          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2323          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2324          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2325          $rc1 = $lpg->create_related_competency(array('competencyid' => $c1->get('id'), 'relatedcompetencyid' => $c2->get('id')));
2326          $rc2 = $lpg->create_related_competency(array('competencyid' => $c2->get('id'), 'relatedcompetencyid' => $c3->get('id')));
2327  
2328          $this->assertEquals(2, related_competency::count_records());
2329  
2330          // Returns false when the relation does not exist.
2331          $result = external::remove_related_competency($c1->get('id'), $c3->get('id'));
2332          $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2333          $this->assertFalse($result);
2334  
2335          // Returns true on success.
2336          $result = external::remove_related_competency($c2->get('id'), $c3->get('id'));
2337          $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2338          $this->assertTrue($result);
2339          $this->assertEquals(1, related_competency::count_records());
2340  
2341          // We don't need to specify competencyid and relatedcompetencyid in the right order.
2342          $result = external::remove_related_competency($c2->get('id'), $c1->get('id'));
2343          $result = external_api::clean_returnvalue(external::remove_related_competency_returns(), $result);
2344          $this->assertTrue($result);
2345          $this->assertEquals(0, related_competency::count_records());
2346      }
2347  
2348      /**
2349       * Test that we can search and include related competencies.
2350       *
2351       * @return void
2352       */
2353      public function test_search_competencies_including_related() {
2354          $this->setUser($this->creator);
2355  
2356          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2357          $framework = $lpg->create_framework();
2358          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2359          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2360          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2361          $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2362          $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2363  
2364          // We have 1-2, 1-3, 2-4, and no relation between 2-3 nor 1-4 nor 5.
2365          $rc12 = $lpg->create_related_competency(array('competencyid' => $c1->get('id'), 'relatedcompetencyid' => $c2->get('id')));
2366          $rc13 = $lpg->create_related_competency(array('competencyid' => $c1->get('id'), 'relatedcompetencyid' => $c3->get('id')));
2367          $rc24 = $lpg->create_related_competency(array('competencyid' => $c2->get('id'), 'relatedcompetencyid' => $c4->get('id')));
2368  
2369          $result = external::search_competencies('comp', $framework->get('id'), true);
2370          $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result);
2371  
2372          $this->assertCount(5, $result);
2373  
2374      }
2375  
2376      /**
2377       * Test that we can add competency to plan if we have the right capability.
2378       *
2379       * @return void
2380       */
2381      public function test_add_competency_to_plan() {
2382          $this->resetAfterTest(true);
2383          $dg = $this->getDataGenerator();
2384          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2385          $usermanage = $dg->create_user();
2386          $user = $dg->create_user();
2387  
2388          $syscontext = context_system::instance();
2389  
2390          // Creating specific roles.
2391          $managerole = $dg->create_role(array(
2392              'name' => 'User manage',
2393              'shortname' => 'manage'
2394          ));
2395  
2396          assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2397          assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2398  
2399          $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2400  
2401          $this->setUser($usermanage);
2402          $plan = array (
2403              'userid' => $usermanage->id,
2404              'status' => \core_competency\plan::STATUS_ACTIVE
2405          );
2406          $pl1 = $lpg->create_plan($plan);
2407          $framework = $lpg->create_framework();
2408          $competency = $lpg->create_competency(
2409                  array('competencyframeworkid' => $framework->get('id'))
2410                  );
2411          $this->assertTrue(external::add_competency_to_plan($pl1->get('id'), $competency->get('id')));
2412  
2413          // A competency cannot be added to plan based on template.
2414          $template = $lpg->create_template();
2415          $plan = array (
2416              'userid' => $usermanage->id,
2417              'status' => \core_competency\plan::STATUS_ACTIVE,
2418              'templateid' => $template->get('id')
2419          );
2420          $pl2 = $lpg->create_plan($plan);
2421          try {
2422              external::add_competency_to_plan($pl2->get('id'), $competency->get('id'));
2423              $this->fail('A competency cannot be added to plan based on template');
2424          } catch (coding_exception $ex) {
2425              $this->assertTrue(true);
2426          }
2427  
2428          // User without capability cannot add competency to a plan.
2429          $this->setUser($user);
2430          try {
2431              external::add_competency_to_plan($pl1->get('id'), $competency->get('id'));
2432              $this->fail('User without capability cannot add competency to a plan');
2433          } catch (required_capability_exception $ex) {
2434              $this->assertTrue(true);
2435          }
2436      }
2437  
2438      /**
2439       * Test that we can add competency to plan if we have the right capability.
2440       *
2441       * @return void
2442       */
2443      public function test_remove_competency_from_plan() {
2444          $this->resetAfterTest(true);
2445          $dg = $this->getDataGenerator();
2446          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2447          $usermanage = $dg->create_user();
2448          $user = $dg->create_user();
2449  
2450          $syscontext = context_system::instance();
2451  
2452          // Creating specific roles.
2453          $managerole = $dg->create_role(array(
2454              'name' => 'User manage',
2455              'shortname' => 'manage'
2456          ));
2457  
2458          assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2459          assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2460  
2461          $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2462  
2463          $this->setUser($usermanage);
2464          $plan = array (
2465              'userid' => $usermanage->id,
2466              'status' => \core_competency\plan::STATUS_ACTIVE
2467          );
2468          $pl1 = $lpg->create_plan($plan);
2469          $framework = $lpg->create_framework();
2470          $competency = $lpg->create_competency(
2471                  array('competencyframeworkid' => $framework->get('id'))
2472                  );
2473          $lpg->create_plan_competency(
2474                  array(
2475                      'planid' => $pl1->get('id'),
2476                      'competencyid' => $competency->get('id')
2477                      )
2478                  );
2479          $this->assertTrue(external::remove_competency_from_plan($pl1->get('id'), $competency->get('id')));
2480          $this->assertCount(0, $pl1->get_competencies());
2481      }
2482  
2483      /**
2484       * Test that we can add competency to plan if we have the right capability.
2485       *
2486       * @return void
2487       */
2488      public function test_reorder_plan_competency() {
2489          $this->resetAfterTest(true);
2490          $dg = $this->getDataGenerator();
2491          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2492          $usermanage = $dg->create_user();
2493          $user = $dg->create_user();
2494  
2495          $syscontext = context_system::instance();
2496  
2497          // Creating specific roles.
2498          $managerole = $dg->create_role(array(
2499              'name' => 'User manage',
2500              'shortname' => 'manage'
2501          ));
2502  
2503          assign_capability('moodle/competency:planmanage', CAP_ALLOW, $managerole, $syscontext->id);
2504          assign_capability('moodle/competency:planview', CAP_ALLOW, $managerole, $syscontext->id);
2505  
2506          $dg->role_assign($managerole, $usermanage->id, $syscontext->id);
2507  
2508          $this->setUser($usermanage);
2509          $plan = array (
2510              'userid' => $usermanage->id,
2511              'status' => \core_competency\plan::STATUS_ACTIVE
2512          );
2513          $pl1 = $lpg->create_plan($plan);
2514          $framework = $lpg->create_framework();
2515          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2516          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2517          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2518          $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2519          $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2520  
2521          $lpg->create_plan_competency(array('planid' => $pl1->get('id'), 'competencyid' => $c1->get('id'), 'sortorder' => 1));
2522          $lpg->create_plan_competency(array('planid' => $pl1->get('id'), 'competencyid' => $c2->get('id'), 'sortorder' => 2));
2523          $lpg->create_plan_competency(array('planid' => $pl1->get('id'), 'competencyid' => $c3->get('id'), 'sortorder' => 3));
2524          $lpg->create_plan_competency(array('planid' => $pl1->get('id'), 'competencyid' => $c4->get('id'), 'sortorder' => 4));
2525          $lpg->create_plan_competency(array('planid' => $pl1->get('id'), 'competencyid' => $c5->get('id'), 'sortorder' => 5));
2526  
2527          // Test if removing competency from plan don't create sortorder holes.
2528          external::remove_competency_from_plan($pl1->get('id'), $c4->get('id'));
2529          $plancomp5 = plan_competency::get_record(array(
2530              'planid' => $pl1->get('id'),
2531              'competencyid' => $c5->get('id')
2532          ));
2533  
2534          $this->assertEquals(3, $plancomp5->get('sortorder'));
2535  
2536          $this->assertTrue(external::reorder_plan_competency($pl1->get('id'), $c2->get('id'), $c5->get('id')));
2537          $this->assertTrue(external::reorder_plan_competency($pl1->get('id'), $c3->get('id'), $c1->get('id')));
2538          $plancompetencies = plan_competency::get_records(array('planid' => $pl1->get('id')), 'sortorder', 'ASC');
2539          $plcmp1 = $plancompetencies[0];
2540          $plcmp2 = $plancompetencies[1];
2541          $plcmp3 = $plancompetencies[2];
2542          $plcmp4 = $plancompetencies[3];
2543  
2544          $this->assertEquals($plcmp1->get('competencyid'), $c3->get('id'));
2545          $this->assertEquals($plcmp2->get('competencyid'), $c1->get('id'));
2546          $this->assertEquals($plcmp3->get('competencyid'), $c5->get('id'));
2547          $this->assertEquals($plcmp4->get('competencyid'), $c2->get('id'));
2548      }
2549  
2550      /**
2551       * Test resolving sortorder when we creating competency.
2552       */
2553      public function test_fix_sortorder_when_creating_competency() {
2554          $this->resetAfterTest(true);
2555          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2556          $framework = $lpg->create_framework();
2557  
2558          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2559          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'sortorder' => 20));
2560          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'sortorder' => 1));
2561  
2562          $this->assertEquals(0, $c1->get('sortorder'));
2563          $this->assertEquals(1, $c2->get('sortorder'));
2564          $this->assertEquals(2, $c3->get('sortorder'));
2565      }
2566  
2567      /**
2568       * Test resolving sortorder when we delete competency.
2569       */
2570      public function test_fix_sortorder_when_delete_competency() {
2571          $this->resetAfterTest(true);
2572          $this->setUser($this->creator);
2573          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2574  
2575          $framework = $lpg->create_framework();
2576  
2577          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2578          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2579          $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2580          $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2581          $c2c = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2582          $c2d = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2583  
2584          $this->assertEquals(0, $c1->get('sortorder'));
2585          $this->assertEquals(1, $c2->get('sortorder'));
2586          $this->assertEquals(0, $c2a->get('sortorder'));
2587          $this->assertEquals(1, $c2b->get('sortorder'));
2588          $this->assertEquals(2, $c2c->get('sortorder'));
2589          $this->assertEquals(3, $c2d->get('sortorder'));
2590  
2591          $result = external::delete_competency($c1->get('id'));
2592          $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2593  
2594          $c2->read();
2595          $c2a->read();
2596          $c2b->read();
2597          $c2c->read();
2598          $c2d->read();
2599  
2600          $this->assertEquals(0, $c2->get('sortorder'));
2601          $this->assertEquals(0, $c2a->get('sortorder'));
2602          $this->assertEquals(1, $c2b->get('sortorder'));
2603          $this->assertEquals(2, $c2c->get('sortorder'));
2604          $this->assertEquals(3, $c2d->get('sortorder'));
2605  
2606          $result = external::delete_competency($c2b->get('id'));
2607          $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result);
2608  
2609          $c2->read();
2610          $c2a->read();
2611          $c2c->read();
2612          $c2d->read();
2613  
2614          $this->assertEquals(0, $c2->get('sortorder'));
2615          $this->assertEquals(0, $c2a->get('sortorder'));
2616          $this->assertEquals(1, $c2c->get('sortorder'));
2617          $this->assertEquals(2, $c2d->get('sortorder'));
2618      }
2619  
2620      /**
2621       * Test resolving sortorder when moving a competency.
2622       */
2623      public function test_fix_sortorder_when_moving_competency() {
2624          $this->resetAfterTest(true);
2625          $this->setUser($this->creator);
2626          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2627  
2628          $framework = $lpg->create_framework();
2629  
2630          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2631          $c1a = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c1->get('id')));
2632          $c1b = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c1->get('id')));
2633          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2634          $c2a = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2635          $c2b = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id'), 'parentid' => $c2->get('id')));
2636  
2637          $this->assertEquals(0, $c1->get('sortorder'));
2638          $this->assertEquals(0, $c1a->get('sortorder'));
2639          $this->assertEquals(1, $c1b->get('sortorder'));
2640          $this->assertEquals(1, $c2->get('sortorder'));
2641          $this->assertEquals(0, $c2a->get('sortorder'));
2642          $this->assertEquals(1, $c2b->get('sortorder'));
2643  
2644          $result = external::set_parent_competency($c2a->get('id'), $c1->get('id'));
2645          $result = external_api::clean_returnvalue(external::set_parent_competency_returns(), $result);
2646  
2647          $c1->read();
2648          $c1a->read();
2649          $c1b->read();
2650          $c2->read();
2651          $c2a->read();
2652          $c2b->read();
2653  
2654          $this->assertEquals(0, $c1->get('sortorder'));
2655          $this->assertEquals(0, $c1a->get('sortorder'));
2656          $this->assertEquals(1, $c1b->get('sortorder'));
2657          $this->assertEquals(2, $c2a->get('sortorder'));
2658          $this->assertEquals(1, $c2->get('sortorder'));
2659          $this->assertEquals(0, $c2b->get('sortorder'));
2660  
2661          // Move a root node.
2662          $result = external::set_parent_competency($c2->get('id'), $c1b->get('id'));
2663          $result = external_api::clean_returnvalue(external::set_parent_competency_returns(), $result);
2664  
2665          $c1->read();
2666          $c1a->read();
2667          $c1b->read();
2668          $c2->read();
2669          $c2a->read();
2670          $c2b->read();
2671  
2672          $this->assertEquals(0, $c1->get('sortorder'));
2673          $this->assertEquals(0, $c1a->get('sortorder'));
2674          $this->assertEquals(1, $c1b->get('sortorder'));
2675          $this->assertEquals(0, $c2->get('sortorder'));
2676          $this->assertEquals(0, $c2b->get('sortorder'));
2677          $this->assertEquals(2, $c2a->get('sortorder'));
2678      }
2679  
2680      public function test_grade_competency() {
2681          global $CFG;
2682  
2683          $this->setUser($this->creator);
2684          $dg = $this->getDataGenerator();
2685          $lpg = $dg->get_plugin_generator('core_competency');
2686  
2687          $f1 = $lpg->create_framework();
2688          $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2689          $evidence = external::grade_competency($this->user->id, $c1->get('id'), 1, 'Evil note');
2690  
2691          $this->assertEquals('The competency rating was manually set.', $evidence->description);
2692          $this->assertEquals('A', $evidence->gradename);
2693          $this->assertEquals('Evil note', $evidence->note);
2694  
2695          $this->setUser($this->user);
2696  
2697          $this->expectException('required_capability_exception');
2698          $evidence = external::grade_competency($this->user->id, $c1->get('id'), 1);
2699      }
2700  
2701      public function test_grade_competency_in_course() {
2702          global $CFG;
2703  
2704          $this->setUser($this->creator);
2705          $dg = $this->getDataGenerator();
2706          $lpg = $dg->get_plugin_generator('core_competency');
2707  
2708          $course = $dg->create_course(['fullname' => 'Evil course']);
2709          $dg->enrol_user($this->creator->id, $course->id, 'editingteacher');
2710          $dg->enrol_user($this->user->id, $course->id, 'student');
2711          $f1 = $lpg->create_framework();
2712          $c1 = $lpg->create_competency(['competencyframeworkid' => $f1->get('id')]);
2713          $lpg->create_course_competency(['courseid' => $course->id, 'competencyid' => $c1->get('id')]);
2714  
2715          $evidence = external::grade_competency_in_course($course->id, $this->user->id, $c1->get('id'), 1, 'Evil note');
2716  
2717          $this->assertEquals('The competency rating was manually set in the course \'Course: Evil course\'.', $evidence->description);
2718          $this->assertEquals('A', $evidence->gradename);
2719          $this->assertEquals('Evil note', $evidence->note);
2720  
2721          $this->setUser($this->user);
2722  
2723          $this->expectException('required_capability_exception');
2724          $evidence = external::grade_competency_in_course($course->id, $this->user->id, $c1->get('id'), 1);
2725      }
2726  
2727      public function test_grade_competency_in_plan() {
2728          global $CFG;
2729  
2730          $this->setUser($this->creator);
2731  
2732          $dg = $this->getDataGenerator();
2733          $lpg = $dg->get_plugin_generator('core_competency');
2734  
2735          $f1 = $lpg->create_framework();
2736  
2737          $c1 = $lpg->create_competency(array('competencyframeworkid' => $f1->get('id')));
2738  
2739          $tpl = $lpg->create_template();
2740          $lpg->create_template_competency(array('templateid' => $tpl->get('id'), 'competencyid' => $c1->get('id')));
2741  
2742          $plan = $lpg->create_plan(array('userid' => $this->user->id, 'templateid' => $tpl->get('id'), 'name' => 'Evil'));
2743  
2744          $uc = $lpg->create_user_competency(array('userid' => $this->user->id, 'competencyid' => $c1->get('id')));
2745  
2746          $evidence = external::grade_competency_in_plan($plan->get('id'), $c1->get('id'), 1, 'Evil note');
2747  
2748          $this->assertEquals('The competency rating was manually set in the learning plan \'Evil\'.', $evidence->description);
2749          $this->assertEquals('A', $evidence->gradename);
2750          $this->assertEquals('Evil note', $evidence->note);
2751  
2752          $this->setUser($this->user);
2753  
2754          $this->expectException('required_capability_exception');
2755          $evidence = external::grade_competency_in_plan($plan->get('id'), $c1->get('id'), 1);
2756      }
2757  
2758      /**
2759       * Test update course competency settings.
2760       */
2761      public function test_update_course_competency_settings() {
2762          $this->resetAfterTest(true);
2763  
2764          $dg = $this->getDataGenerator();
2765  
2766          $course = $dg->create_course();
2767          $roleid = $dg->create_role();
2768          $noobroleid = $dg->create_role();
2769          $context = context_course::instance($course->id);
2770          $compmanager = $this->getDataGenerator()->create_user();
2771          $compnoob = $this->getDataGenerator()->create_user();
2772  
2773          assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $roleid, $context->id, true);
2774          assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $roleid, $context->id, true);
2775          assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $noobroleid, $context->id, true);
2776  
2777          role_assign($roleid, $compmanager->id, $context->id);
2778          role_assign($noobroleid, $compnoob->id, $context->id);
2779          $dg->enrol_user($compmanager->id, $course->id, $roleid);
2780          $dg->enrol_user($compnoob->id, $course->id, $noobroleid);
2781  
2782          $this->setUser($compmanager);
2783  
2784          // Start the test.
2785          $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2786  
2787          $settings = course_competency_settings::get_by_courseid($course->id);
2788  
2789          $this->assertTrue((bool)$settings->get('pushratingstouserplans'));
2790  
2791          $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => false));
2792  
2793          $settings = course_competency_settings::get_by_courseid($course->id);
2794  
2795          $this->assertFalse((bool)$settings->get('pushratingstouserplans'));
2796          $this->setUser($compnoob);
2797  
2798          $this->expectException('required_capability_exception');
2799          $result = external::update_course_competency_settings($course->id, array('pushratingstouserplans' => true));
2800      }
2801  
2802      /**
2803       * Test that we can list competencies with a filter.
2804       *
2805       * @return void
2806       */
2807      public function test_list_competencies_with_filter() {
2808          $this->resetAfterTest(true);
2809          $this->setAdminUser();
2810          $dg = $this->getDataGenerator();
2811          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2812  
2813          $framework = $lpg->create_framework();
2814          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2815          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2816          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2817          $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2818          $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2819  
2820          // Test if removing competency from plan don't create sortorder holes.
2821          $filters = [];
2822          $sort = 'id';
2823          $order = 'ASC';
2824          $skip = 0;
2825          $limit = 0;
2826          $result = external::list_competencies($filters, $sort, $order, $skip, $limit);
2827          $this->assertCount(5, $result);
2828  
2829          $result = external::list_competencies($filters, $sort, $order, 2, $limit);
2830          $this->assertCount(3, $result);
2831          $result = external::list_competencies($filters, $sort, $order, 2, 2);
2832          $this->assertCount(2, $result);
2833  
2834          $filter = $result[0]->shortname;
2835          $filters[0] = ['column' => 'shortname', 'value' => $filter];
2836          $result = external::list_competencies($filters, $sort, $order, $skip, $limit);
2837          $this->assertCount(1, $result);
2838          $this->assertEquals($filter, $result[0]->shortname);
2839      }
2840  
2841      /**
2842       * Test that we can list competencies with a course module.
2843       *
2844       * @return void
2845       */
2846      public function test_list_competencies_with_course_module() {
2847          $this->resetAfterTest(true);
2848          $this->setAdminUser();
2849          $dg = $this->getDataGenerator();
2850          $lpg = $this->getDataGenerator()->get_plugin_generator('core_competency');
2851          $course = $dg->create_course();
2852  
2853          $framework = $lpg->create_framework();
2854          $c1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2855          $c2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2856          $c3 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2857          $c4 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2858          $c5 = $lpg->create_competency(array('competencyframeworkid' => $framework->get('id')));
2859  
2860          $cc1 = api::add_competency_to_course($course->id, $c1->get('id'));
2861          $cc2 = api::add_competency_to_course($course->id, $c2->get('id'));
2862          $cc3 = api::add_competency_to_course($course->id, $c3->get('id'));
2863  
2864          $pagegenerator = $this->getDataGenerator()->get_plugin_generator('mod_page');
2865          $page = $pagegenerator->create_instance(array('course' => $course->id));
2866  
2867          $cm = get_coursemodule_from_instance('page', $page->id);
2868          // Add a link and list again.
2869          $ccm1 = api::add_competency_to_course_module($cm, $c1->get('id'));
2870          $ccm2 = api::add_competency_to_course_module($cm, $c2->get('id'));
2871  
2872          // Test list competencies for this course module.
2873          $total = external::count_course_module_competencies($cm->id);
2874          $result = external::list_course_module_competencies($cm->id);
2875          $this->assertCount($total, $result);
2876  
2877          // Now we should have an array and each element of the array should have a competency and
2878          // a coursemodulecompetency.
2879          foreach ($result as $instance) {
2880              $cmc = $instance['coursemodulecompetency'];
2881              $c = $instance['competency'];
2882              $this->assertEquals($cmc->competencyid, $c->id);
2883          }
2884  
2885      }
2886  
2887  }