Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

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

Differences Between: [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * External glossary functions unit tests
  19   *
  20   * @package    mod_glossary
  21   * @category   external
  22   * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  global $CFG;
  28  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  29  
  30  /**
  31   * External glossary functions unit tests
  32   *
  33   * @package    mod_glossary
  34   * @category   external
  35   * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class mod_glossary_external_testcase extends externallib_advanced_testcase {
  39  
  40      /**
  41       * Test get_glossaries_by_courses
  42       */
  43      public function test_get_glossaries_by_courses() {
  44          $this->resetAfterTest(true);
  45  
  46          // As admin.
  47          $this->setAdminUser();
  48          $c1 = self::getDataGenerator()->create_course();
  49          $c2 = self::getDataGenerator()->create_course();
  50          $g1 = self::getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'name' => 'First Glossary'));
  51          $g2 = self::getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'name' => 'Second Glossary'));
  52          $g3 = self::getDataGenerator()->create_module('glossary', array('course' => $c2->id, 'name' => 'Third Glossary'));
  53  
  54          $s1 = $this->getDataGenerator()->create_user();
  55          self::getDataGenerator()->enrol_user($s1->id,  $c1->id);
  56  
  57          // Check results where student is enrolled.
  58          $this->setUser($s1);
  59          $glossaries = mod_glossary_external::get_glossaries_by_courses(array());
  60          $glossaries = external_api::clean_returnvalue(mod_glossary_external::get_glossaries_by_courses_returns(), $glossaries);
  61  
  62          $this->assertCount(2, $glossaries['glossaries']);
  63          $this->assertEquals('First Glossary', $glossaries['glossaries'][0]['name']);
  64          $this->assertEquals('Second Glossary', $glossaries['glossaries'][1]['name']);
  65          $this->assertEquals(1, $glossaries['glossaries'][0]['canaddentry']);
  66          $this->assertEquals(1, $glossaries['glossaries'][1]['canaddentry']);
  67  
  68          // Check results with specific course IDs.
  69          $glossaries = mod_glossary_external::get_glossaries_by_courses(array($c1->id, $c2->id));
  70          $glossaries = external_api::clean_returnvalue(mod_glossary_external::get_glossaries_by_courses_returns(), $glossaries);
  71  
  72          $this->assertCount(2, $glossaries['glossaries']);
  73          $this->assertEquals('First Glossary', $glossaries['glossaries'][0]['name']);
  74          $this->assertEquals('Second Glossary', $glossaries['glossaries'][1]['name']);
  75  
  76          $this->assertEquals('course', $glossaries['warnings'][0]['item']);
  77          $this->assertEquals($c2->id, $glossaries['warnings'][0]['itemid']);
  78          $this->assertEquals('1', $glossaries['warnings'][0]['warningcode']);
  79          $this->assertEquals(1, $glossaries['glossaries'][0]['canaddentry']);
  80  
  81          // Now as admin.
  82          $this->setAdminUser();
  83  
  84          $glossaries = mod_glossary_external::get_glossaries_by_courses(array($c2->id));
  85          $glossaries = external_api::clean_returnvalue(mod_glossary_external::get_glossaries_by_courses_returns(), $glossaries);
  86  
  87          $this->assertCount(1, $glossaries['glossaries']);
  88          $this->assertEquals('Third Glossary', $glossaries['glossaries'][0]['name']);
  89          $this->assertEquals(1, $glossaries['glossaries'][0]['canaddentry']);
  90      }
  91  
  92      public function test_view_glossary() {
  93          $this->resetAfterTest(true);
  94  
  95          // Generate all the things.
  96          $c1 = $this->getDataGenerator()->create_course();
  97          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
  98          $u1 = $this->getDataGenerator()->create_user();
  99          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 100  
 101          $sink = $this->redirectEvents();
 102          $this->setUser($u1);
 103          $return = mod_glossary_external::view_glossary($g1->id, 'letter');
 104          $return = external_api::clean_returnvalue(mod_glossary_external::view_glossary_returns(), $return);
 105          $events = $sink->get_events();
 106  
 107          // Assertion.
 108          $this->assertTrue($return['status']);
 109          $this->assertEmpty($return['warnings']);
 110          $this->assertCount(1, $events);
 111          $this->assertEquals('\mod_glossary\event\course_module_viewed', $events[0]->eventname);
 112          $sink->close();
 113      }
 114  
 115      /**
 116       * @expectedException        require_login_exception
 117       * @expectedExceptionMessage Activity is hidden
 118       */
 119      public function test_view_glossary_without_permission() {
 120          $this->resetAfterTest(true);
 121  
 122          // Generate all the things.
 123          $c1 = $this->getDataGenerator()->create_course();
 124          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 125          $u1 = $this->getDataGenerator()->create_user();
 126          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 127          $ctx = context_module::instance($g1->cmid);
 128  
 129          // Revoke permission.
 130          $roles = get_archetype_roles('user');
 131          $role = array_shift($roles);
 132          assign_capability('mod/glossary:view', CAP_PROHIBIT, $role->id, $ctx, true);
 133          accesslib_clear_all_caches_for_unit_testing();
 134  
 135          // Assertion.
 136          $this->setUser($u1);
 137          mod_glossary_external::view_glossary($g1->id, 'letter');
 138      }
 139  
 140      /**
 141       * @expectedException        require_login_exception
 142       * @expectedExceptionMessage Activity is hidden
 143       */
 144      public function test_view_entry() {
 145          $this->resetAfterTest(true);
 146  
 147          // Generate all the things.
 148          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 149          $c1 = $this->getDataGenerator()->create_course();
 150          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 151          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'visible' => false));
 152          $u1 = $this->getDataGenerator()->create_user();
 153          $e1 = $gg->create_content($g1, array('approved' => 1));
 154          $e2 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u1->id));
 155          $e3 = $gg->create_content($g1, array('approved' => 0, 'userid' => -1));
 156          $e4 = $gg->create_content($g2, array('approved' => 1));
 157          $ctx = context_module::instance($g1->cmid);
 158          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 159          $this->setUser($u1);
 160  
 161          // Test readable entry.
 162          $sink = $this->redirectEvents();
 163          $return = mod_glossary_external::view_entry($e1->id);
 164          $return = external_api::clean_returnvalue(mod_glossary_external::view_entry_returns(), $return);
 165          $events = $sink->get_events();
 166          $this->assertTrue($return['status']);
 167          $this->assertEmpty($return['warnings']);
 168          $this->assertCount(1, $events);
 169          $this->assertEquals('\mod_glossary\event\entry_viewed', $events[0]->eventname);
 170          $sink->close();
 171  
 172          // Test non-approved of self.
 173          $return = mod_glossary_external::view_entry($e2->id);
 174          $return = external_api::clean_returnvalue(mod_glossary_external::view_entry_returns(), $return);
 175          $events = $sink->get_events();
 176          $this->assertTrue($return['status']);
 177          $this->assertEmpty($return['warnings']);
 178          $this->assertCount(1, $events);
 179          $this->assertEquals('\mod_glossary\event\entry_viewed', $events[0]->eventname);
 180          $sink->close();
 181  
 182          // Test non-approved of other.
 183          try {
 184              mod_glossary_external::view_entry($e3->id);
 185              $this->fail('Cannot view non-approved entries of others.');
 186          } catch (invalid_parameter_exception $e) {
 187              // All good.
 188          }
 189  
 190          // Test non-readable entry.
 191          mod_glossary_external::view_entry($e4->id);
 192      }
 193  
 194      public function test_get_entries_by_letter() {
 195          $this->resetAfterTest(true);
 196  
 197          // Generate all the things.
 198          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 199          $c1 = $this->getDataGenerator()->create_course();
 200          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 201          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 202          $u1 = $this->getDataGenerator()->create_user();
 203          $ctx = context_module::instance($g1->cmid);
 204          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 205  
 206          $e1a = $gg->create_content($g1, array('approved' => 0, 'concept' => 'Bob', 'userid' => 2, 'tags' => array('Cats', 'Dogs')));
 207          $e1b = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Jane', 'userid' => 2));
 208          $e1c = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Alice', 'userid' => $u1->id));
 209          $e1d = $gg->create_content($g1, array('approved' => 0, 'concept' => '0-day', 'userid' => $u1->id));
 210          $e2a = $gg->create_content($g2);
 211  
 212          $this->setAdminUser();
 213  
 214          // Just a normal request from admin user.
 215          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 0, 20, array());
 216          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 217          $this->assertCount(3, $return['entries']);
 218          $this->assertEquals(3, $return['count']);
 219          $this->assertEquals($e1c->id, $return['entries'][0]['id']);
 220          $this->assertEquals($e1a->id, $return['entries'][1]['id']);
 221          $this->assertEquals('Cats', $return['entries'][1]['tags'][0]['rawname']);
 222          $this->assertEquals('Dogs', $return['entries'][1]['tags'][1]['rawname']);
 223          $this->assertEquals($e1b->id, $return['entries'][2]['id']);
 224  
 225          // An admin user requesting all the entries.
 226          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 0, 20, array('includenotapproved' => 1));
 227          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 228          $this->assertCount(4, $return['entries']);
 229          $this->assertEquals(4, $return['count']);
 230          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
 231          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 232          $this->assertEquals($e1a->id, $return['entries'][2]['id']);
 233          $this->assertEquals($e1b->id, $return['entries'][3]['id']);
 234  
 235          // A normal user.
 236          $this->setUser($u1);
 237          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 0, 20, array());
 238          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 239          $this->assertCount(3, $return['entries']);
 240          $this->assertEquals(3, $return['count']);
 241          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
 242          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 243          $this->assertEquals($e1b->id, $return['entries'][2]['id']);
 244  
 245          // A normal user requesting to view all non approved entries.
 246          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 0, 20, array('includenotapproved' => 1));
 247          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 248          $this->assertCount(3, $return['entries']);
 249          $this->assertEquals(3, $return['count']);
 250          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
 251          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 252          $this->assertEquals($e1b->id, $return['entries'][2]['id']);
 253      }
 254  
 255      public function test_get_entries_by_letter_with_parameters() {
 256          $this->resetAfterTest(true);
 257  
 258          // Generate all the things.
 259          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 260          $c1 = $this->getDataGenerator()->create_course();
 261          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 262          $u1 = $this->getDataGenerator()->create_user();
 263          $ctx = context_module::instance($g1->cmid);
 264          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 265  
 266          $e1a = $gg->create_content($g1, array('approved' => 1, 'concept' => '0-day', 'userid' => $u1->id));
 267          $e1b = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Bob', 'userid' => 2));
 268          $e1c = $gg->create_content($g1, array('approved' => 1, 'concept' => '1-dayb', 'userid' => $u1->id));
 269  
 270          $this->setUser($u1);
 271  
 272          // Requesting a single letter.
 273          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'b', 0, 20, array());
 274          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 275          $this->assertCount(1, $return['entries']);
 276          $this->assertEquals(1, $return['count']);
 277          $this->assertEquals($e1b->id, $return['entries'][0]['id']);
 278  
 279          // Requesting special letters.
 280          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'SPECIAL', 0, 20, array());
 281          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 282          $this->assertCount(2, $return['entries']);
 283          $this->assertEquals(2, $return['count']);
 284          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 285          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 286  
 287          // Requesting with limit.
 288          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 0, 1, array());
 289          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 290          $this->assertCount(1, $return['entries']);
 291          $this->assertEquals(3, $return['count']);
 292          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 293          $return = mod_glossary_external::get_entries_by_letter($g1->id, 'ALL', 1, 2, array());
 294          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_letter_returns(), $return);
 295          $this->assertCount(2, $return['entries']);
 296          $this->assertEquals(3, $return['count']);
 297          $this->assertEquals($e1c->id, $return['entries'][0]['id']);
 298          $this->assertEquals($e1b->id, $return['entries'][1]['id']);
 299      }
 300  
 301      public function test_get_entries_by_date() {
 302          global $DB;
 303          $this->resetAfterTest(true);
 304  
 305          // Generate all the things.
 306          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 307          $c1 = $this->getDataGenerator()->create_course();
 308          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 309          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 310          $u1 = $this->getDataGenerator()->create_user();
 311          $ctx = context_module::instance($g1->cmid);
 312          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 313  
 314          $now = time();
 315          $e1a = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Bob', 'userid' => $u1->id,
 316              'timecreated' => 1, 'timemodified' => $now + 3600, 'tags' => array('Cats', 'Dogs')));
 317          $e1b = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Jane', 'userid' => $u1->id,
 318              'timecreated' => $now + 3600, 'timemodified' => 1));
 319          $e1c = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Alice', 'userid' => $u1->id,
 320              'timecreated' => $now + 1, 'timemodified' => $now + 1));
 321          $e1d = $gg->create_content($g1, array('approved' => 0, 'concept' => '0-day', 'userid' => $u1->id,
 322              'timecreated' => $now + 2, 'timemodified' => $now + 2));
 323          $e2a = $gg->create_content($g2);
 324  
 325          $this->setAdminUser($u1);
 326  
 327          // Ordering by time modified descending.
 328          $return = mod_glossary_external::get_entries_by_date($g1->id, 'UPDATE', 'DESC', 0, 20, array());
 329          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 330          $this->assertCount(3, $return['entries']);
 331          $this->assertEquals(3, $return['count']);
 332          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 333          $this->assertEquals('Cats', $return['entries'][0]['tags'][0]['rawname']);
 334          $this->assertEquals('Dogs', $return['entries'][0]['tags'][1]['rawname']);
 335          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 336          $this->assertEquals($e1b->id, $return['entries'][2]['id']);
 337  
 338          // Ordering by time modified ascending.
 339          $return = mod_glossary_external::get_entries_by_date($g1->id, 'UPDATE', 'ASC', 0, 20, array());
 340          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 341          $this->assertCount(3, $return['entries']);
 342          $this->assertEquals(3, $return['count']);
 343          $this->assertEquals($e1b->id, $return['entries'][0]['id']);
 344          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 345          $this->assertEquals($e1a->id, $return['entries'][2]['id']);
 346  
 347          // Ordering by time created asc.
 348          $return = mod_glossary_external::get_entries_by_date($g1->id, 'CREATION', 'ASC', 0, 20, array());
 349          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 350          $this->assertCount(3, $return['entries']);
 351          $this->assertEquals(3, $return['count']);
 352          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 353          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 354          $this->assertEquals($e1b->id, $return['entries'][2]['id']);
 355  
 356          // Ordering by time created descending.
 357          $return = mod_glossary_external::get_entries_by_date($g1->id, 'CREATION', 'DESC', 0, 20, array());
 358          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 359          $this->assertCount(3, $return['entries']);
 360          $this->assertEquals(3, $return['count']);
 361          $this->assertEquals($e1b->id, $return['entries'][0]['id']);
 362          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 363          $this->assertEquals($e1a->id, $return['entries'][2]['id']);
 364  
 365          // Ordering including to approve.
 366          $return = mod_glossary_external::get_entries_by_date($g1->id, 'CREATION', 'ASC', 0, 20,
 367              array('includenotapproved' => true));
 368          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 369          $this->assertCount(4, $return['entries']);
 370          $this->assertEquals(4, $return['count']);
 371          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 372          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 373          $this->assertEquals($e1d->id, $return['entries'][2]['id']);
 374          $this->assertEquals($e1b->id, $return['entries'][3]['id']);
 375  
 376          // Ordering including to approve and pagination.
 377          $return = mod_glossary_external::get_entries_by_date($g1->id, 'CREATION', 'ASC', 0, 2,
 378              array('includenotapproved' => true));
 379          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 380          $this->assertCount(2, $return['entries']);
 381          $this->assertEquals(4, $return['count']);
 382          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
 383          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 384          $return = mod_glossary_external::get_entries_by_date($g1->id, 'CREATION', 'ASC', 2, 2,
 385              array('includenotapproved' => true));
 386          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_date_returns(), $return);
 387          $this->assertCount(2, $return['entries']);
 388          $this->assertEquals(4, $return['count']);
 389          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
 390          $this->assertEquals($e1b->id, $return['entries'][1]['id']);
 391      }
 392  
 393      public function test_get_categories() {
 394          $this->resetAfterTest(true);
 395          $this->setAdminUser();
 396  
 397          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 398          $c1 = $this->getDataGenerator()->create_course();
 399          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 400          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 401          $cat1a = $gg->create_category($g1);
 402          $cat1b = $gg->create_category($g1);
 403          $cat1c = $gg->create_category($g1);
 404          $cat2a = $gg->create_category($g2);
 405  
 406          $return = mod_glossary_external::get_categories($g1->id, 0, 20);
 407          $return = external_api::clean_returnvalue(mod_glossary_external::get_categories_returns(), $return);
 408          $this->assertCount(3, $return['categories']);
 409          $this->assertEquals(3, $return['count']);
 410          $this->assertEquals($cat1a->id, $return['categories'][0]['id']);
 411          $this->assertEquals($cat1b->id, $return['categories'][1]['id']);
 412          $this->assertEquals($cat1c->id, $return['categories'][2]['id']);
 413  
 414          $return = mod_glossary_external::get_categories($g1->id, 1, 2);
 415          $return = external_api::clean_returnvalue(mod_glossary_external::get_categories_returns(), $return);
 416          $this->assertCount(2, $return['categories']);
 417          $this->assertEquals(3, $return['count']);
 418          $this->assertEquals($cat1b->id, $return['categories'][0]['id']);
 419          $this->assertEquals($cat1c->id, $return['categories'][1]['id']);
 420      }
 421  
 422      public function test_get_entries_by_category() {
 423          $this->resetAfterTest(true);
 424  
 425          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 426          $c1 = $this->getDataGenerator()->create_course();
 427          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 428          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 429          $u1 = $this->getDataGenerator()->create_user();
 430          $ctx = context_module::instance($g1->cmid);
 431  
 432          $e1a1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id, 'tags' => array('Cats', 'Dogs')));
 433          $e1a2 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 434          $e1a3 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 435          $e1b1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 436          $e1b2 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u1->id));
 437          $e1x1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 438          $e1x2 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u1->id));
 439          $e2a1 = $gg->create_content($g2, array('approved' => 1, 'userid' => $u1->id));
 440          $e2a2 = $gg->create_content($g2, array('approved' => 1, 'userid' => $u1->id));
 441  
 442          $cat1a = $gg->create_category($g1, array('name' => 'Fish'), array($e1a1, $e1a2, $e1a3));
 443          $cat1b = $gg->create_category($g1, array('name' => 'Cat'), array($e1b1, $e1b2));
 444          $cat1c = $gg->create_category($g1, array('name' => 'Zebra'), array($e1b1));   // Entry $e1b1 is in two categories.
 445          $cat2a = $gg->create_category($g2, array(), array($e2a1, $e2a2));
 446  
 447          $this->setAdminUser();
 448  
 449          // Browse one category.
 450          $return = mod_glossary_external::get_entries_by_category($g1->id, $cat1a->id, 0, 20, array());
 451          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 452          $this->assertCount(3, $return['entries']);
 453          $this->assertEquals(3, $return['count']);
 454          $this->assertEquals($e1a1->id, $return['entries'][0]['id']);
 455          $this->assertEquals('Cats', $return['entries'][0]['tags'][0]['rawname']);
 456          $this->assertEquals('Dogs', $return['entries'][0]['tags'][1]['rawname']);
 457          $this->assertEquals($e1a2->id, $return['entries'][1]['id']);
 458          $this->assertEquals($e1a3->id, $return['entries'][2]['id']);
 459  
 460          // Browse all categories.
 461          $return = mod_glossary_external::get_entries_by_category($g1->id, GLOSSARY_SHOW_ALL_CATEGORIES, 0, 20, array());
 462          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 463          $this->assertCount(5, $return['entries']);
 464          $this->assertEquals(5, $return['count']);
 465          $this->assertEquals($e1b1->id, $return['entries'][0]['id']);
 466          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 467          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 468          $this->assertEquals($e1a3->id, $return['entries'][3]['id']);
 469          $this->assertEquals($e1b1->id, $return['entries'][4]['id']);
 470  
 471          // Browse uncategorised.
 472          $return = mod_glossary_external::get_entries_by_category($g1->id, GLOSSARY_SHOW_NOT_CATEGORISED, 0, 20, array());
 473          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 474          $this->assertCount(1, $return['entries']);
 475          $this->assertEquals(1, $return['count']);
 476          $this->assertEquals($e1x1->id, $return['entries'][0]['id']);
 477  
 478          // Including to approve.
 479          $return = mod_glossary_external::get_entries_by_category($g1->id, $cat1b->id, 0, 20,
 480              array('includenotapproved' => true));
 481          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 482          $this->assertCount(2, $return['entries']);
 483          $this->assertEquals(2, $return['count']);
 484          $this->assertEquals($e1b1->id, $return['entries'][0]['id']);
 485          $this->assertEquals($e1b2->id, $return['entries'][1]['id']);
 486  
 487          // Using limit.
 488          $return = mod_glossary_external::get_entries_by_category($g1->id, GLOSSARY_SHOW_ALL_CATEGORIES, 0, 3,
 489              array('includenotapproved' => true));
 490          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 491          $this->assertCount(3, $return['entries']);
 492          $this->assertEquals(6, $return['count']);
 493          $this->assertEquals($e1b1->id, $return['entries'][0]['id']);
 494          $this->assertEquals($e1b2->id, $return['entries'][1]['id']);
 495          $this->assertEquals($e1a1->id, $return['entries'][2]['id']);
 496          $return = mod_glossary_external::get_entries_by_category($g1->id, GLOSSARY_SHOW_ALL_CATEGORIES, 3, 2,
 497              array('includenotapproved' => true));
 498          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_category_returns(), $return);
 499          $this->assertCount(2, $return['entries']);
 500          $this->assertEquals(6, $return['count']);
 501          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 502          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 503      }
 504  
 505      public function test_get_authors() {
 506          $this->resetAfterTest(true);
 507  
 508          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 509          $c1 = $this->getDataGenerator()->create_course();
 510          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 511          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 512  
 513          $u1 = $this->getDataGenerator()->create_user(array('lastname' => 'Upsilon'));
 514          $u2 = $this->getDataGenerator()->create_user(array('lastname' => 'Alpha'));
 515          $u3 = $this->getDataGenerator()->create_user(array('lastname' => 'Omega'));
 516  
 517          $ctx = context_module::instance($g1->cmid);
 518  
 519          $e1a = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1));
 520          $e1b = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1));
 521          $e1c = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1));
 522          $e2a = $gg->create_content($g1, array('userid' => $u2->id, 'approved' => 1));
 523          $e3a = $gg->create_content($g1, array('userid' => $u3->id, 'approved' => 0));
 524  
 525          $this->setAdminUser();
 526  
 527          // Simple request.
 528          $return = mod_glossary_external::get_authors($g1->id, 0, 20, array());
 529          $return = external_api::clean_returnvalue(mod_glossary_external::get_authors_returns(), $return);
 530          $this->assertCount(2, $return['authors']);
 531          $this->assertEquals(2, $return['count']);
 532          $this->assertEquals($u2->id, $return['authors'][0]['id']);
 533          $this->assertEquals($u1->id, $return['authors'][1]['id']);
 534  
 535          // Include users with entries pending approval.
 536          $return = mod_glossary_external::get_authors($g1->id, 0, 20, array('includenotapproved' => true));
 537          $return = external_api::clean_returnvalue(mod_glossary_external::get_authors_returns(), $return);
 538          $this->assertCount(3, $return['authors']);
 539          $this->assertEquals(3, $return['count']);
 540          $this->assertEquals($u2->id, $return['authors'][0]['id']);
 541          $this->assertEquals($u3->id, $return['authors'][1]['id']);
 542          $this->assertEquals($u1->id, $return['authors'][2]['id']);
 543  
 544          // Pagination.
 545          $return = mod_glossary_external::get_authors($g1->id, 1, 1, array('includenotapproved' => true));
 546          $return = external_api::clean_returnvalue(mod_glossary_external::get_authors_returns(), $return);
 547          $this->assertCount(1, $return['authors']);
 548          $this->assertEquals(3, $return['count']);
 549          $this->assertEquals($u3->id, $return['authors'][0]['id']);
 550      }
 551  
 552      public function test_get_entries_by_author() {
 553          $this->resetAfterTest(true);
 554  
 555          // Generate all the things.
 556          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 557          $c1 = $this->getDataGenerator()->create_course();
 558          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 559          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 560          $u1 = $this->getDataGenerator()->create_user(array('lastname' => 'Upsilon', 'firstname' => 'Zac'));
 561          $u2 = $this->getDataGenerator()->create_user(array('lastname' => 'Ultra', 'firstname' => '1337'));
 562          $u3 = $this->getDataGenerator()->create_user(array('lastname' => 'Alpha', 'firstname' => 'Omega'));
 563          $u4 = $this->getDataGenerator()->create_user(array('lastname' => '0-day', 'firstname' => 'Zoe'));
 564          $ctx = context_module::instance($g1->cmid);
 565          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 566  
 567          $e1a1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 568          $e1a2 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 569          $e1a3 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id));
 570          $e1b1 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u2->id));
 571          $e1b2 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u2->id, 'tags' => array('Cats', 'Dogs')));
 572          $e1c1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u3->id));
 573          $e1d1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u4->id));
 574          $e2a = $gg->create_content($g2, array('approved' => 1, 'userid' => $u1->id));
 575  
 576          $this->setUser($u1);
 577  
 578          // Requesting a single letter.
 579          $return = mod_glossary_external::get_entries_by_author($g1->id, 'u', 'LASTNAME', 'ASC', 0, 20, array());
 580          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 581          $this->assertCount(4, $return['entries']);
 582          $this->assertEquals(4, $return['count']);
 583          $this->assertEquals($e1b2->id, $return['entries'][0]['id']);
 584          $this->assertEquals('Cats', $return['entries'][0]['tags'][0]['rawname']);
 585          $this->assertEquals('Dogs', $return['entries'][0]['tags'][1]['rawname']);
 586          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 587          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 588          $this->assertEquals($e1a3->id, $return['entries'][3]['id']);
 589  
 590          // Requesting special letters.
 591          $return = mod_glossary_external::get_entries_by_author($g1->id, 'SPECIAL', 'LASTNAME', 'ASC', 0, 20, array());
 592          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 593          $this->assertCount(1, $return['entries']);
 594          $this->assertEquals(1, $return['count']);
 595          $this->assertEquals($e1d1->id, $return['entries'][0]['id']);
 596  
 597          // Requesting with limit.
 598          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'LASTNAME', 'ASC', 0, 1, array());
 599          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 600          $this->assertCount(1, $return['entries']);
 601          $this->assertEquals(6, $return['count']);
 602          $this->assertEquals($e1d1->id, $return['entries'][0]['id']);
 603          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'LASTNAME', 'ASC', 1, 2, array());
 604          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 605          $this->assertCount(2, $return['entries']);
 606          $this->assertEquals(6, $return['count']);
 607          $this->assertEquals($e1c1->id, $return['entries'][0]['id']);
 608          $this->assertEquals($e1b2->id, $return['entries'][1]['id']);
 609  
 610          // Including non-approved.
 611          $this->setAdminUser();
 612          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'LASTNAME', 'ASC', 0, 20,
 613              array('includenotapproved' => true));
 614          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 615          $this->assertCount(7, $return['entries']);
 616          $this->assertEquals(7, $return['count']);
 617          $this->assertEquals($e1d1->id, $return['entries'][0]['id']);
 618          $this->assertEquals($e1c1->id, $return['entries'][1]['id']);
 619          $this->assertEquals($e1b1->id, $return['entries'][2]['id']);
 620          $this->assertEquals($e1b2->id, $return['entries'][3]['id']);
 621          $this->assertEquals($e1a1->id, $return['entries'][4]['id']);
 622          $this->assertEquals($e1a2->id, $return['entries'][5]['id']);
 623          $this->assertEquals($e1a3->id, $return['entries'][6]['id']);
 624  
 625          // Changing order.
 626          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'LASTNAME', 'DESC', 0, 1, array());
 627          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 628          $this->assertCount(1, $return['entries']);
 629          $this->assertEquals(6, $return['count']);
 630          $this->assertEquals($e1a1->id, $return['entries'][0]['id']);
 631  
 632          // Sorting by firstname.
 633          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'FIRSTNAME', 'ASC', 0, 1, array());
 634          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 635          $this->assertCount(1, $return['entries']);
 636          $this->assertEquals(6, $return['count']);
 637          $this->assertEquals($e1b2->id, $return['entries'][0]['id']);
 638  
 639          // Sorting by firstname descending.
 640          $return = mod_glossary_external::get_entries_by_author($g1->id, 'ALL', 'FIRSTNAME', 'DESC', 0, 1, array());
 641          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 642          $this->assertCount(1, $return['entries']);
 643          $this->assertEquals(6, $return['count']);
 644          $this->assertEquals($e1d1->id, $return['entries'][0]['id']);
 645  
 646          // Filtering by firstname descending.
 647          $return = mod_glossary_external::get_entries_by_author($g1->id, 'z', 'FIRSTNAME', 'DESC', 0, 20, array());
 648          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 649          $this->assertCount(4, $return['entries']);
 650          $this->assertEquals(4, $return['count']);
 651          $this->assertEquals($e1d1->id, $return['entries'][0]['id']);
 652          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 653          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 654          $this->assertEquals($e1a3->id, $return['entries'][3]['id']);
 655  
 656          // Test with a deleted user.
 657          delete_user($u2);
 658          $return = mod_glossary_external::get_entries_by_author($g1->id, 'u', 'LASTNAME', 'ASC', 0, 20, array());
 659          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_returns(), $return);
 660          $this->assertCount(4, $return['entries']);
 661          $this->assertEquals(4, $return['count']);
 662          $this->assertEquals($e1b2->id, $return['entries'][0]['id']);
 663          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 664          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 665          $this->assertEquals($e1a3->id, $return['entries'][3]['id']);
 666      }
 667  
 668      public function test_get_entries_by_author_id() {
 669          $this->resetAfterTest(true);
 670  
 671          // Generate all the things.
 672          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 673          $c1 = $this->getDataGenerator()->create_course();
 674          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 675          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'displayformat' => 'entrylist'));
 676          $u1 = $this->getDataGenerator()->create_user(array('lastname' => 'Upsilon', 'firstname' => 'Zac'));
 677          $u2 = $this->getDataGenerator()->create_user(array('lastname' => 'Ultra', 'firstname' => '1337'));
 678          $u3 = $this->getDataGenerator()->create_user(array('lastname' => 'Alpha', 'firstname' => 'Omega'));
 679          $u4 = $this->getDataGenerator()->create_user(array('lastname' => '0-day', 'firstname' => 'Zoe'));
 680          $ctx = context_module::instance($g1->cmid);
 681          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 682  
 683          $e1a1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id, 'concept' => 'Zoom',
 684              'timecreated' => 3600, 'timemodified' => time() - 3600));
 685          $e1a2 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id, 'concept' => 'Alpha'));
 686          $e1a3 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id, 'concept' => 'Dog',
 687              'timecreated' => 1, 'timemodified' => time() - 1800));
 688          $e1a4 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u1->id, 'concept' => 'Bird'));
 689          $e1b1 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u2->id));
 690          $e2a = $gg->create_content($g2, array('approved' => 1, 'userid' => $u1->id));
 691  
 692          $this->setAdminUser();
 693  
 694          // Standard request.
 695          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CONCEPT', 'ASC', 0, 20, array());
 696          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 697          $this->assertCount(3, $return['entries']);
 698          $this->assertEquals(3, $return['count']);
 699          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 700          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 701          $this->assertEquals($e1a1->id, $return['entries'][2]['id']);
 702  
 703          // Standard request descending.
 704          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CONCEPT', 'DESC', 0, 20, array());
 705          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 706          $this->assertCount(3, $return['entries']);
 707          $this->assertEquals(3, $return['count']);
 708          $this->assertEquals($e1a1->id, $return['entries'][0]['id']);
 709          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 710          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 711  
 712          // Requesting ordering by time created.
 713          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CREATION', 'ASC', 0, 20, array());
 714          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 715          $this->assertCount(3, $return['entries']);
 716          $this->assertEquals(3, $return['count']);
 717          $this->assertEquals($e1a3->id, $return['entries'][0]['id']);
 718          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 719          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 720  
 721          // Requesting ordering by time created descending.
 722          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CREATION', 'DESC', 0, 20, array());
 723          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 724          $this->assertCount(3, $return['entries']);
 725          $this->assertEquals(3, $return['count']);
 726          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 727          $this->assertEquals($e1a1->id, $return['entries'][1]['id']);
 728          $this->assertEquals($e1a3->id, $return['entries'][2]['id']);
 729  
 730          // Requesting ordering by time modified.
 731          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'UPDATE', 'ASC', 0, 20, array());
 732          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 733          $this->assertCount(3, $return['entries']);
 734          $this->assertEquals(3, $return['count']);
 735          $this->assertEquals($e1a1->id, $return['entries'][0]['id']);
 736          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 737          $this->assertEquals($e1a2->id, $return['entries'][2]['id']);
 738  
 739          // Requesting ordering by time modified descending.
 740          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'UPDATE', 'DESC', 0, 20, array());
 741          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 742          $this->assertCount(3, $return['entries']);
 743          $this->assertEquals(3, $return['count']);
 744          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 745          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 746          $this->assertEquals($e1a1->id, $return['entries'][2]['id']);
 747  
 748          // Including non approved.
 749          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CONCEPT', 'ASC', 0, 20,
 750              array('includenotapproved' => true));
 751          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 752          $this->assertCount(4, $return['entries']);
 753          $this->assertEquals(4, $return['count']);
 754          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 755          $this->assertEquals($e1a4->id, $return['entries'][1]['id']);
 756          $this->assertEquals($e1a3->id, $return['entries'][2]['id']);
 757          $this->assertEquals($e1a1->id, $return['entries'][3]['id']);
 758  
 759          // Pagination.
 760          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CONCEPT', 'ASC', 0, 2,
 761              array('includenotapproved' => true));
 762          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 763          $this->assertCount(2, $return['entries']);
 764          $this->assertEquals(4, $return['count']);
 765          $this->assertEquals($e1a2->id, $return['entries'][0]['id']);
 766          $this->assertEquals($e1a4->id, $return['entries'][1]['id']);
 767          $return = mod_glossary_external::get_entries_by_author_id($g1->id, $u1->id, 'CONCEPT', 'ASC', 1, 2,
 768              array('includenotapproved' => true));
 769          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_author_id_returns(), $return);
 770          $this->assertCount(2, $return['entries']);
 771          $this->assertEquals(4, $return['count']);
 772          $this->assertEquals($e1a4->id, $return['entries'][0]['id']);
 773          $this->assertEquals($e1a3->id, $return['entries'][1]['id']);
 774      }
 775  
 776      public function test_get_entries_by_search() {
 777          $this->resetAfterTest(true);
 778  
 779          // Generate all the things.
 780          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 781          $c1 = $this->getDataGenerator()->create_course();
 782          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 783          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 784          $u1 = $this->getDataGenerator()->create_user();
 785          $ctx = context_module::instance($g1->cmid);
 786          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 787          $this->setUser($u1);
 788  
 789          $e1 = $gg->create_content($g1, array('approved' => 1, 'concept' => 'House', 'timecreated' => time() + 3600));
 790          $e2 = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Mouse', 'timemodified' => 1));
 791          $e3 = $gg->create_content($g1, array('approved' => 1, 'concept' => 'Hero', 'tags' => array('Cats', 'Dogs')));
 792          $e4 = $gg->create_content($g1, array('approved' => 0, 'concept' => 'Toulouse'));
 793          $e5 = $gg->create_content($g1, array('approved' => 1, 'definition' => 'Heroes', 'concept' => 'Abcd'));
 794          $e6 = $gg->create_content($g1, array('approved' => 0, 'definition' => 'When used for Heroes'));
 795          $e7 = $gg->create_content($g1, array('approved' => 1, 'timecreated' => 1, 'timemodified' => time() + 3600,
 796              'concept' => 'Z'), array('Couscous'));
 797          $e8 = $gg->create_content($g1, array('approved' => 0), array('Heroes'));
 798          $e9 = $gg->create_content($g2, array('approved' => 0));
 799  
 800          $this->setAdminUser();
 801  
 802          // Test simple query.
 803          $query = 'hero';
 804          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'CONCEPT', 'ASC', 0, 20, array());
 805          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 806          $this->assertCount(1, $return['entries']);
 807          $this->assertEquals(1, $return['count']);
 808          $this->assertEquals($e3->id, $return['entries'][0]['id']);
 809          $this->assertEquals('Cats', $return['entries'][0]['tags'][0]['rawname']);
 810          $this->assertEquals('Dogs', $return['entries'][0]['tags'][1]['rawname']);
 811  
 812          // Enabling full search.
 813          $query = 'hero';
 814          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, true, 'CONCEPT', 'ASC', 0, 20, array());
 815          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 816          $this->assertCount(2, $return['entries']);
 817          $this->assertEquals(2, $return['count']);
 818          $this->assertEquals($e5->id, $return['entries'][0]['id']);
 819          $this->assertEquals($e3->id, $return['entries'][1]['id']);
 820  
 821          // Concept descending.
 822          $query = 'hero';
 823          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, true, 'CONCEPT', 'DESC', 0, 20, array());
 824          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 825          $this->assertCount(2, $return['entries']);
 826          $this->assertEquals(2, $return['count']);
 827          $this->assertEquals($e3->id, $return['entries'][0]['id']);
 828          $this->assertEquals($e5->id, $return['entries'][1]['id']);
 829  
 830          // Search on alias.
 831          $query = 'couscous';
 832          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'CONCEPT', 'ASC', 0, 20, array());
 833          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 834          $this->assertCount(1, $return['entries']);
 835          $this->assertEquals(1, $return['count']);
 836          $this->assertEquals($e7->id, $return['entries'][0]['id']);
 837          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, true, 'CONCEPT', 'ASC', 0, 20, array());
 838          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 839          $this->assertCount(1, $return['entries']);
 840          $this->assertEquals(1, $return['count']);
 841          $this->assertEquals($e7->id, $return['entries'][0]['id']);
 842  
 843          // Pagination and ordering on created date.
 844          $query = 'ou';
 845          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'CREATION', 'ASC', 0, 1, array());
 846          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 847          $this->assertCount(1, $return['entries']);
 848          $this->assertEquals(3, $return['count']);
 849          $this->assertEquals($e7->id, $return['entries'][0]['id']);
 850          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'CREATION', 'DESC', 0, 1, array());
 851          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 852          $this->assertCount(1, $return['entries']);
 853          $this->assertEquals(3, $return['count']);
 854          $this->assertEquals($e1->id, $return['entries'][0]['id']);
 855  
 856          // Ordering on updated date.
 857          $query = 'ou';
 858          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'UPDATE', 'ASC', 0, 1, array());
 859          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 860          $this->assertCount(1, $return['entries']);
 861          $this->assertEquals(3, $return['count']);
 862          $this->assertEquals($e2->id, $return['entries'][0]['id']);
 863          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'UPDATE', 'DESC', 0, 1, array());
 864          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 865          $this->assertCount(1, $return['entries']);
 866          $this->assertEquals(3, $return['count']);
 867          $this->assertEquals($e7->id, $return['entries'][0]['id']);
 868  
 869          // Including not approved.
 870          $query = 'ou';
 871          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, false, 'CONCEPT', 'ASC', 0, 20,
 872              array('includenotapproved' => true));
 873          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 874          $this->assertCount(4, $return['entries']);
 875          $this->assertEquals(4, $return['count']);
 876          $this->assertEquals($e1->id, $return['entries'][0]['id']);
 877          $this->assertEquals($e2->id, $return['entries'][1]['id']);
 878          $this->assertEquals($e4->id, $return['entries'][2]['id']);
 879          $this->assertEquals($e7->id, $return['entries'][3]['id']);
 880  
 881          // Advanced query string.
 882          $query = '+Heroes -Abcd';
 883          $return = mod_glossary_external::get_entries_by_search($g1->id, $query, true, 'CONCEPT', 'ASC', 0, 20,
 884              array('includenotapproved' => true));
 885          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_search_returns(), $return);
 886          $this->assertCount(2, $return['entries']);
 887          $this->assertEquals(2, $return['count']);
 888          $this->assertEquals($e6->id, $return['entries'][0]['id']);
 889          $this->assertEquals($e8->id, $return['entries'][1]['id']);
 890      }
 891  
 892      public function test_get_entries_by_term() {
 893          $this->resetAfterTest(true);
 894  
 895          // Generate all the things.
 896          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 897          $c1 = $this->getDataGenerator()->create_course();
 898          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 899          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 900          $u1 = $this->getDataGenerator()->create_user();
 901          $ctx = context_module::instance($g1->cmid);
 902          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 903  
 904          $this->setAdminUser();
 905  
 906          $e1 = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1, 'concept' => 'cat',
 907              'tags' => array('Cats', 'Dogs')));
 908          $e2 = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1), array('cat', 'dog'));
 909          $e3 = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 1), array('dog'));
 910          $e4 = $gg->create_content($g1, array('userid' => $u1->id, 'approved' => 0, 'concept' => 'dog'));
 911          $e5 = $gg->create_content($g2, array('userid' => $u1->id, 'approved' => 1, 'concept' => 'dog'), array('cat'));
 912  
 913          // Search concept + alias.
 914          $return = mod_glossary_external::get_entries_by_term($g1->id, 'cat', 0, 20, array('includenotapproved' => false));
 915          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_term_returns(), $return);
 916          $this->assertCount(2, $return['entries']);
 917          $this->assertEquals(2, $return['count']);
 918          // Compare ids, ignore ordering of array, using canonicalize parameter of assertEquals.
 919          $expected = array($e1->id, $e2->id);
 920          $actual = array($return['entries'][0]['id'], $return['entries'][1]['id']);
 921          $this->assertEquals($expected, $actual, '', 0.0, 10, true);
 922          // Compare rawnames of all expected tags, ignore ordering of array, using canonicalize parameter of assertEquals.
 923          $expected = array('Cats', 'Dogs'); // Only $e1 has 2 tags.
 924          $actual = array(); // Accumulate all tags returned.
 925          foreach ($return['entries'] as $entry) {
 926              foreach ($entry['tags'] as $tag) {
 927                  $actual[] = $tag['rawname'];
 928              }
 929          }
 930          $this->assertEquals($expected, $actual, '', 0.0, 10, true);
 931  
 932          // Search alias.
 933          $return = mod_glossary_external::get_entries_by_term($g1->id, 'dog', 0, 20, array('includenotapproved' => false));
 934          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_term_returns(), $return);
 935  
 936          $this->assertCount(2, $return['entries']);
 937          $this->assertEquals(2, $return['count']);
 938          // Compare ids, ignore ordering of array, using canonicalize parameter of assertEquals.
 939          $expected = array($e2->id, $e3->id);
 940          $actual = array($return['entries'][0]['id'], $return['entries'][1]['id']);
 941          $this->assertEquals($expected, $actual, '', 0.0, 10, true);
 942  
 943          // Search including not approved.
 944          $return = mod_glossary_external::get_entries_by_term($g1->id, 'dog', 0, 20, array('includenotapproved' => true));
 945          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_term_returns(), $return);
 946          $this->assertCount(3, $return['entries']);
 947          $this->assertEquals(3, $return['count']);
 948          // Compare ids, ignore ordering of array, using canonicalize parameter of assertEquals.
 949          $expected = array($e4->id, $e2->id, $e3->id);
 950          $actual = array($return['entries'][0]['id'], $return['entries'][1]['id'], $return['entries'][2]['id']);
 951          $this->assertEquals($expected, $actual, '', 0.0, 10, true);
 952  
 953          // Pagination.
 954          $return = mod_glossary_external::get_entries_by_term($g1->id, 'dog', 0, 1, array('includenotapproved' => true));
 955          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_term_returns(), $return);
 956          $this->assertCount(1, $return['entries']);
 957          // We don't compare the returned entry id because it may be different depending on the DBMS,
 958          // for example, Postgres does a random sorting in this case.
 959          $this->assertEquals(3, $return['count']);
 960          $return = mod_glossary_external::get_entries_by_term($g1->id, 'dog', 1, 1, array('includenotapproved' => true));
 961          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_by_term_returns(), $return);
 962          $this->assertCount(1, $return['entries']);
 963          $this->assertEquals(3, $return['count']);
 964      }
 965  
 966      public function test_get_entries_to_approve() {
 967          $this->resetAfterTest(true);
 968  
 969          // Generate all the things.
 970          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
 971          $c1 = $this->getDataGenerator()->create_course();
 972          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 973          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
 974          $u1 = $this->getDataGenerator()->create_user();
 975          $ctx = context_module::instance($g1->cmid);
 976          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
 977  
 978          $e1a = $gg->create_content($g1, array('approved' => 0, 'concept' => 'Bob', 'userid' => $u1->id,
 979              'timecreated' => time() + 3600));
 980          $e1b = $gg->create_content($g1, array('approved' => 0, 'concept' => 'Jane', 'userid' => $u1->id, 'timecreated' => 1));
 981          $e1c = $gg->create_content($g1, array('approved' => 0, 'concept' => 'Alice', 'userid' => $u1->id, 'timemodified' => 1));
 982          $e1d = $gg->create_content($g1, array('approved' => 0, 'concept' => '0-day', 'userid' => $u1->id,
 983              'timemodified' => time() + 3600));
 984          $e1e = $gg->create_content($g1, array('approved' => 1, 'concept' => '1-day', 'userid' => $u1->id));
 985          $e2a = $gg->create_content($g2);
 986  
 987          $this->setAdminUser(true);
 988  
 989          // Simple listing.
 990          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CONCEPT', 'ASC', 0, 20);
 991          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
 992          $this->assertCount(4, $return['entries']);
 993          $this->assertEquals(4, $return['count']);
 994          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
 995          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
 996          $this->assertEquals($e1a->id, $return['entries'][2]['id']);
 997          $this->assertEquals($e1b->id, $return['entries'][3]['id']);
 998  
 999          // Revert ordering of concept.
1000          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CONCEPT', 'DESC', 0, 20);
1001          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1002          $this->assertCount(4, $return['entries']);
1003          $this->assertEquals(4, $return['count']);
1004          $this->assertEquals($e1b->id, $return['entries'][0]['id']);
1005          $this->assertEquals($e1a->id, $return['entries'][1]['id']);
1006          $this->assertEquals($e1c->id, $return['entries'][2]['id']);
1007          $this->assertEquals($e1d->id, $return['entries'][3]['id']);
1008  
1009          // Filtering by letter.
1010          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'a', 'CONCEPT', 'ASC', 0, 20);
1011          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1012          $this->assertCount(1, $return['entries']);
1013          $this->assertEquals(1, $return['count']);
1014          $this->assertEquals($e1c->id, $return['entries'][0]['id']);
1015  
1016          // Filtering by special.
1017          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'SPECIAL', 'CONCEPT', 'ASC', 0, 20);
1018          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1019          $this->assertCount(1, $return['entries']);
1020          $this->assertEquals(1, $return['count']);
1021          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
1022  
1023          // Pagination.
1024          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CONCEPT', 'ASC', 0, 2);
1025          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1026          $this->assertCount(2, $return['entries']);
1027          $this->assertEquals(4, $return['count']);
1028          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
1029          $this->assertEquals($e1c->id, $return['entries'][1]['id']);
1030          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CONCEPT', 'ASC', 1, 2);
1031          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1032          $this->assertCount(2, $return['entries']);
1033          $this->assertEquals(4, $return['count']);
1034          $this->assertEquals($e1c->id, $return['entries'][0]['id']);
1035          $this->assertEquals($e1a->id, $return['entries'][1]['id']);
1036  
1037          // Ordering by creation date.
1038          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CREATION', 'ASC', 0, 1);
1039          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1040          $this->assertCount(1, $return['entries']);
1041          $this->assertEquals(4, $return['count']);
1042          $this->assertEquals($e1b->id, $return['entries'][0]['id']);
1043  
1044          // Ordering by creation date desc.
1045          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CREATION', 'DESC', 0, 1);
1046          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1047          $this->assertCount(1, $return['entries']);
1048          $this->assertEquals(4, $return['count']);
1049          $this->assertEquals($e1a->id, $return['entries'][0]['id']);
1050  
1051          // Ordering by update date.
1052          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'UPDATE', 'ASC', 0, 1);
1053          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1054          $this->assertCount(1, $return['entries']);
1055          $this->assertEquals(4, $return['count']);
1056          $this->assertEquals($e1c->id, $return['entries'][0]['id']);
1057  
1058          // Ordering by update date desc.
1059          $return = mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'UPDATE', 'DESC', 0, 1);
1060          $return = external_api::clean_returnvalue(mod_glossary_external::get_entries_to_approve_returns(), $return);
1061          $this->assertCount(1, $return['entries']);
1062          $this->assertEquals(4, $return['count']);
1063          $this->assertEquals($e1d->id, $return['entries'][0]['id']);
1064  
1065          // Permissions are checked.
1066          $this->setUser($u1);
1067          $this->expectException('required_capability_exception');
1068          mod_glossary_external::get_entries_to_approve($g1->id, 'ALL', 'CONCEPT', 'ASC', 0, 1);
1069          $this->fail('Do not test anything else after this.');
1070      }
1071  
1072      public function test_get_entry_by_id() {
1073          $this->resetAfterTest(true);
1074  
1075          // Generate all the things.
1076          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
1077          $c1 = $this->getDataGenerator()->create_course();
1078          $c2 = $this->getDataGenerator()->create_course();
1079          $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id));
1080          $g2 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id, 'visible' => 0));
1081          $u1 = $this->getDataGenerator()->create_user();
1082          $u2 = $this->getDataGenerator()->create_user();
1083          $ctx = context_module::instance($g1->cmid);
1084          $this->getDataGenerator()->enrol_user($u1->id, $c1->id);
1085  
1086          $e1 = $gg->create_content($g1, array('approved' => 1, 'userid' => $u1->id, 'tags' => array('Cats', 'Dogs')));
1087          // Add a fake inline image to the entry.
1088          $filename = 'shouldbeanimage.jpg';
1089          $filerecordinline = array(
1090              'contextid' => $ctx->id,
1091              'component' => 'mod_glossary',
1092              'filearea'  => 'entry',
1093              'itemid'    => $e1->id,
1094              'filepath'  => '/',
1095              'filename'  => $filename,
1096          );
1097          $fs = get_file_storage();
1098          $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
1099  
1100          $e2 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u1->id));
1101          $e3 = $gg->create_content($g1, array('approved' => 0, 'userid' => $u2->id));
1102          $e4 = $gg->create_content($g2, array('approved' => 1));
1103  
1104          $this->setUser($u1);
1105          $return = mod_glossary_external::get_entry_by_id($e1->id);
1106          $return = external_api::clean_returnvalue(mod_glossary_external::get_entry_by_id_returns(), $return);
1107          $this->assertEquals($e1->id, $return['entry']['id']);
1108          $this->assertEquals('Cats', $return['entry']['tags'][0]['rawname']);
1109          $this->assertEquals('Dogs', $return['entry']['tags'][1]['rawname']);
1110          $this->assertEquals($filename, $return['entry']['definitioninlinefiles'][0]['filename']);
1111  
1112          $return = mod_glossary_external::get_entry_by_id($e2->id);
1113          $return = external_api::clean_returnvalue(mod_glossary_external::get_entry_by_id_returns(), $return);
1114          $this->assertEquals($e2->id, $return['entry']['id']);
1115  
1116          try {
1117              $return = mod_glossary_external::get_entry_by_id($e3->id);
1118              $this->fail('Cannot view unapproved entries of others.');
1119          } catch (invalid_parameter_exception $e) {
1120              // All good.
1121          }
1122  
1123          try {
1124              $return = mod_glossary_external::get_entry_by_id($e4->id);
1125              $this->fail('Cannot view entries from another course.');
1126          } catch (require_login_exception $e) {
1127              // All good.
1128          }
1129  
1130          // An admin can be other's entries to be approved.
1131          $this->setAdminUser();
1132          $return = mod_glossary_external::get_entry_by_id($e3->id);
1133          $return = external_api::clean_returnvalue(mod_glossary_external::get_entry_by_id_returns(), $return);
1134          $this->assertEquals($e3->id, $return['entry']['id']);
1135      }
1136  
1137      public function test_add_entry_without_optional_settings() {
1138          global $CFG, $DB;
1139          $this->resetAfterTest(true);
1140  
1141          $course = $this->getDataGenerator()->create_course();
1142          $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id));
1143  
1144          $this->setAdminUser();
1145          $concept = 'A concept';
1146          $definition = '<p>A definition</p>';
1147          $return = mod_glossary_external::add_entry($glossary->id, $concept, $definition, FORMAT_HTML);
1148          $return = external_api::clean_returnvalue(mod_glossary_external::add_entry_returns(), $return);
1149  
1150          // Get entry from DB.
1151          $entry = $DB->get_record('glossary_entries', array('id' => $return['entryid']));
1152  
1153          $this->assertEquals($concept, $entry->concept);
1154          $this->assertEquals($definition, $entry->definition);
1155          $this->assertEquals($CFG->glossary_linkentries, $entry->usedynalink);
1156          $this->assertEquals($CFG->glossary_casesensitive, $entry->casesensitive);
1157          $this->assertEquals($CFG->glossary_fullmatch, $entry->fullmatch);
1158          $this->assertEmpty($DB->get_records('glossary_alias', array('entryid' => $return['entryid'])));
1159          $this->assertEmpty($DB->get_records('glossary_entries_categories', array('entryid' => $return['entryid'])));
1160      }
1161  
1162      public function test_add_entry_with_aliases() {
1163          global $DB;
1164          $this->resetAfterTest(true);
1165  
1166          $course = $this->getDataGenerator()->create_course();
1167          $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id));
1168  
1169          $this->setAdminUser();
1170          $concept = 'A concept';
1171          $definition = 'A definition';
1172          $paramaliases = 'abc, def, gez';
1173          $options = array(
1174              array(
1175                  'name' => 'aliases',
1176                  'value' => $paramaliases,
1177              )
1178          );
1179          $return = mod_glossary_external::add_entry($glossary->id, $concept, $definition, FORMAT_HTML, $options);
1180          $return = external_api::clean_returnvalue(mod_glossary_external::add_entry_returns(), $return);
1181  
1182          $aliases = $DB->get_records('glossary_alias', array('entryid' => $return['entryid']));
1183          $this->assertCount(3, $aliases);
1184          foreach ($aliases as $alias) {
1185              $this->assertContains($alias->alias, $paramaliases);
1186          }
1187      }
1188  
1189      public function test_add_entry_in_categories() {
1190          global $DB;
1191          $this->resetAfterTest(true);
1192  
1193          $course = $this->getDataGenerator()->create_course();
1194          $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id));
1195          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
1196          $cat1 = $gg->create_category($glossary);
1197          $cat2 = $gg->create_category($glossary);
1198  
1199          $this->setAdminUser();
1200          $concept = 'A concept';
1201          $definition = 'A definition';
1202          $paramcategories = "$cat1->id, $cat2->id";
1203          $options = array(
1204              array(
1205                  'name' => 'categories',
1206                  'value' => $paramcategories,
1207              )
1208          );
1209          $return = mod_glossary_external::add_entry($glossary->id, $concept, $definition, FORMAT_HTML, $options);
1210          $return = external_api::clean_returnvalue(mod_glossary_external::add_entry_returns(), $return);
1211  
1212          $categories = $DB->get_records('glossary_entries_categories', array('entryid' => $return['entryid']));
1213          $this->assertCount(2, $categories);
1214          foreach ($categories as $category) {
1215              $this->assertContains($category->categoryid, $paramcategories);
1216          }
1217      }
1218  
1219      public function test_add_entry_with_attachments() {
1220          global $DB, $USER;
1221          $this->resetAfterTest(true);
1222  
1223          $course = $this->getDataGenerator()->create_course();
1224          $glossary = $this->getDataGenerator()->create_module('glossary', array('course' => $course->id));
1225          $context = context_module::instance($glossary->cmid);
1226  
1227          $this->setAdminUser();
1228          $concept = 'A concept';
1229          $definition = 'A definition';
1230  
1231          // Draft files.
1232          $draftidinlineattach = file_get_unused_draft_itemid();
1233          $draftidattach = file_get_unused_draft_itemid();
1234          $usercontext = context_user::instance($USER->id);
1235          $filerecordinline = array(
1236              'contextid' => $usercontext->id,
1237              'component' => 'user',
1238              'filearea'  => 'draft',
1239              'itemid'    => $draftidinlineattach,
1240              'filepath'  => '/',
1241              'filename'  => 'shouldbeanimage.txt',
1242          );
1243          $fs = get_file_storage();
1244  
1245          // Create a file in a draft area for regular attachments.
1246          $filerecordattach = $filerecordinline;
1247          $attachfilename = 'attachment.txt';
1248          $filerecordattach['filename'] = $attachfilename;
1249          $filerecordattach['itemid'] = $draftidattach;
1250          $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
1251          $fs->create_file_from_string($filerecordattach, 'simple text attachment');
1252  
1253          $options = array(
1254              array(
1255                  'name' => 'inlineattachmentsid',
1256                  'value' => $draftidinlineattach,
1257              ),
1258              array(
1259                  'name' => 'attachmentsid',
1260                  'value' => $draftidattach,
1261              )
1262          );
1263          $return = mod_glossary_external::add_entry($glossary->id, $concept, $definition, FORMAT_HTML, $options);
1264          $return = external_api::clean_returnvalue(mod_glossary_external::add_entry_returns(), $return);
1265  
1266          $editorfiles = external_util::get_area_files($context->id, 'mod_glossary', 'entry', $return['entryid']);
1267          $attachmentfiles = external_util::get_area_files($context->id, 'mod_glossary', 'attachment', $return['entryid']);
1268  
1269          $this->assertCount(1, $editorfiles);
1270          $this->assertCount(1, $attachmentfiles);
1271  
1272          $this->assertEquals('shouldbeanimage.txt', $editorfiles[0]['filename']);
1273          $this->assertEquals('attachment.txt', $attachmentfiles[0]['filename']);
1274      }
1275  
1276      /**
1277       *   Test get entry including rating information.
1278       */
1279      public function test_get_entry_rating_information() {
1280          $this->resetAfterTest(true);
1281  
1282          global $DB, $CFG;
1283          require_once($CFG->dirroot . '/rating/lib.php');
1284  
1285          $this->resetAfterTest(true);
1286  
1287          $user1 = self::getDataGenerator()->create_user();
1288          $user2 = self::getDataGenerator()->create_user();
1289          $user3 = self::getDataGenerator()->create_user();
1290          $teacher = self::getDataGenerator()->create_user();
1291  
1292          // Create course to add the module.
1293          $course = self::getDataGenerator()->create_course();
1294  
1295          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
1296          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
1297          $this->getDataGenerator()->enrol_user($user1->id, $course->id, $studentrole->id, 'manual');
1298          $this->getDataGenerator()->enrol_user($user2->id, $course->id, $studentrole->id, 'manual');
1299          $this->getDataGenerator()->enrol_user($user3->id, $course->id, $studentrole->id, 'manual');
1300          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
1301  
1302          // Create the glossary and contents.
1303          $record = new stdClass();
1304          $record->course = $course->id;
1305          $record->assessed = RATING_AGGREGATE_AVERAGE;
1306          $scale = $this->getDataGenerator()->create_scale(array('scale' => 'A,B,C,D'));
1307          $record->scale = "-$scale->id";
1308          $glossary = $this->getDataGenerator()->create_module('glossary', $record);
1309          $context = context_module::instance($glossary->cmid);
1310  
1311          $gg = $this->getDataGenerator()->get_plugin_generator('mod_glossary');
1312          $entry = $gg->create_content($glossary, array('approved' => 1, 'userid' => $user1->id));
1313  
1314          // Rate the entry as user2.
1315          $rating1 = new stdClass();
1316          $rating1->contextid = $context->id;
1317          $rating1->component = 'mod_glossary';
1318          $rating1->ratingarea = 'entry';
1319          $rating1->itemid = $entry->id;
1320          $rating1->rating = 1; // 1 is A.
1321          $rating1->scaleid = "-$scale->id";
1322          $rating1->userid = $user2->id;
1323          $rating1->timecreated = time();
1324          $rating1->timemodified = time();
1325          $rating1->id = $DB->insert_record('rating', $rating1);
1326  
1327          // Rate the entry as user3.
1328          $rating2 = new stdClass();
1329          $rating2->contextid = $context->id;
1330          $rating2->component = 'mod_glossary';
1331          $rating2->ratingarea = 'entry';
1332          $rating2->itemid = $entry->id;
1333          $rating2->rating = 3; // 3 is C.
1334          $rating2->scaleid = "-$scale->id";
1335          $rating2->userid = $user3->id;
1336          $rating2->timecreated = time() + 1;
1337          $rating2->timemodified = time() + 1;
1338          $rating2->id = $DB->insert_record('rating', $rating2);
1339  
1340          // As student, retrieve ratings information.
1341          $this->setUser($user1);
1342          $result = mod_glossary_external::get_entry_by_id($entry->id);
1343          $result = external_api::clean_returnvalue(mod_glossary_external::get_entry_by_id_returns(), $result);
1344          $this->assertCount(1, $result['ratinginfo']['ratings']);
1345          $this->assertFalse($result['ratinginfo']['ratings'][0]['canviewaggregate']);
1346          $this->assertFalse($result['ratinginfo']['canviewall']);
1347          $this->assertFalse($result['ratinginfo']['ratings'][0]['canrate']);
1348          $this->assertTrue(!isset($result['ratinginfo']['ratings'][0]['count']));
1349  
1350          // Now, as teacher, I should see the info correctly.
1351          $this->setUser($teacher);
1352          $result = mod_glossary_external::get_entry_by_id($entry->id);
1353          $result = external_api::clean_returnvalue(mod_glossary_external::get_entry_by_id_returns(), $result);
1354          $this->assertCount(1, $result['ratinginfo']['ratings']);
1355          $this->assertTrue($result['ratinginfo']['ratings'][0]['canviewaggregate']);
1356          $this->assertTrue($result['ratinginfo']['canviewall']);
1357          $this->assertTrue($result['ratinginfo']['ratings'][0]['canrate']);
1358          $this->assertEquals(2, $result['ratinginfo']['ratings'][0]['count']);
1359          $this->assertEquals(2, $result['ratinginfo']['ratings'][0]['aggregate']);   // 2 is B, that is the average of A + C.
1360      }
1361  }