Search moodle.org's
Developer Documentation

See Release Notes

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