Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]

   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 rating functions unit tests
  19   *
  20   * @package    core_rating
  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  namespace core_rating;
  27  
  28  use core_external\external_api;
  29  use core_rating_external;
  30  use externallib_advanced_testcase;
  31  
  32  defined('MOODLE_INTERNAL') || die();
  33  
  34  global $CFG;
  35  
  36  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  37  require_once($CFG->dirroot . '/rating/lib.php');
  38  
  39  /**
  40   * External rating functions unit tests
  41   *
  42   * @package    core_rating
  43   * @category   external
  44   * @copyright  2015 Costantino Cito <ccito@cvaconsulting.com>
  45   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  46   */
  47  class externallib_test extends externallib_advanced_testcase {
  48  
  49      /** @var \stdClass course record. */
  50      protected $course;
  51  
  52      /** @var \stdClass user record. */
  53      protected $student1;
  54  
  55      /** @var \stdClass user record. */
  56      protected $teacher1;
  57  
  58      /** @var \stdClass user record. */
  59      protected $student2;
  60  
  61      /** @var \stdClass user record. */
  62      protected $teacher2;
  63  
  64      /** @var \stdClass user record. */
  65      protected $student3;
  66  
  67      /** @var \stdClass user record. */
  68      protected $teacher3;
  69  
  70      /** @var \stdClass activity record. */
  71      protected $forum;
  72  
  73      /** @var \stdClass activity record. */
  74      protected $discussion;
  75  
  76      /** @var int context instance ID. */
  77      protected $contextid;
  78  
  79      /** @var \stdClass forum post. */
  80      protected $post;
  81  
  82      /** @var \stdClass a fieldset object, false or exception if error not found. */
  83      protected $studentrole;
  84  
  85      /** @var \stdClass a fieldset object, false or exception if error not found. */
  86      protected $teacherrole;
  87  
  88      /*
  89       * Set up for every test
  90       */
  91      public function setUp(): void {
  92          global $DB;
  93          $this->resetAfterTest();
  94  
  95          $this->course = self::getDataGenerator()->create_course();
  96          $this->student1 = $this->getDataGenerator()->create_user();
  97          $this->student2 = $this->getDataGenerator()->create_user();
  98          $this->teacher1 = $this->getDataGenerator()->create_user();
  99          $this->teacher2 = $this->getDataGenerator()->create_user();
 100          $this->teacher3 = $this->getDataGenerator()->create_user();
 101          $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
 102          $this->teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
 103          unassign_capability('moodle/site:accessallgroups', $this->teacherrole->id);
 104  
 105          $this->getDataGenerator()->enrol_user($this->student1->id, $this->course->id, $this->studentrole->id);
 106          $this->getDataGenerator()->enrol_user($this->student2->id, $this->course->id, $this->studentrole->id);
 107          $this->getDataGenerator()->enrol_user($this->teacher1->id, $this->course->id, $this->teacherrole->id);
 108          $this->getDataGenerator()->enrol_user($this->teacher2->id, $this->course->id, $this->teacherrole->id);
 109          $this->getDataGenerator()->enrol_user($this->teacher3->id, $this->course->id, $this->teacherrole->id);
 110  
 111          // Create the forum.
 112          $record = new \stdClass();
 113          $record->introformat = FORMAT_HTML;
 114          $record->course = $this->course->id;
 115          // Set Aggregate type = Average of ratings.
 116          $record->assessed = RATING_AGGREGATE_AVERAGE;
 117          $record->scale = 100;
 118          $this->forum = self::getDataGenerator()->create_module('forum', $record);
 119  
 120          $this->contextid = \context_module::instance($this->forum->cmid)->id;
 121  
 122          // Add discussion to the forums.
 123          $record = new \stdClass();
 124          $record->course = $this->course->id;
 125          $record->userid = $this->student1->id;
 126          $record->forum = $this->forum->id;
 127          $this->discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 128          // Retrieve the first post.
 129          $this->post = $DB->get_record('forum_posts', array('discussion' => $this->discussion->id));
 130      }
 131  
 132      /**
 133       * Test get_item_ratings
 134       */
 135      public function test_get_item_ratings() {
 136          global $DB;
 137  
 138          // Rete the discussion as teacher1.
 139          $rating1 = new \stdClass();
 140          $rating1->contextid = $this->contextid;
 141          $rating1->component = 'mod_forum';
 142          $rating1->ratingarea = 'post';
 143          $rating1->itemid = $this->post->id;
 144          $rating1->rating = 90;
 145          $rating1->scaleid = 100;
 146          $rating1->userid = $this->teacher1->id;
 147          $rating1->timecreated = time();
 148          $rating1->timemodified = time();
 149          $rating1->id = $DB->insert_record('rating', $rating1);
 150  
 151          // Rete the discussion as teacher2.
 152          $rating2 = new \stdClass();
 153          $rating2->contextid = $this->contextid;
 154          $rating2->component = 'mod_forum';
 155          $rating2->ratingarea = 'post';
 156          $rating2->itemid = $this->post->id;
 157          $rating2->rating = 95;
 158          $rating2->scaleid = 100;
 159          $rating2->userid = $this->teacher2->id;
 160          $rating2->timecreated = time() + 1;
 161          $rating2->timemodified = time() + 1;
 162          $rating2->id = $DB->insert_record('rating', $rating2);
 163  
 164          // Delete teacher2, we must still receive the ratings.
 165          delete_user($this->teacher2);
 166  
 167          // Teachers can see all the ratings.
 168          $this->setUser($this->teacher1);
 169  
 170          $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100, '');
 171          // We need to execute the return values cleaning process to simulate the web service server.
 172          $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
 173          $this->assertCount(2, $ratings['ratings']);
 174  
 175          $indexedratings = array();
 176          foreach ($ratings['ratings'] as $rating) {
 177              $indexedratings[$rating['id']] = $rating;
 178          }
 179          $this->assertEquals($rating1->rating.' / '.$rating1->scaleid, $indexedratings[$rating1->id]['rating']);
 180          $this->assertEquals($rating2->rating.' / '.$rating2->scaleid, $indexedratings[$rating2->id]['rating']);
 181  
 182          $this->assertEquals($rating1->userid, $indexedratings[$rating1->id]['userid']);
 183          $this->assertEquals($rating2->userid, $indexedratings[$rating2->id]['userid']);
 184  
 185          // Student can see ratings.
 186          $this->setUser($this->student1);
 187  
 188          $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100, '');
 189          // We need to execute the return values cleaning process to simulate the web service server.
 190          $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
 191          $this->assertCount(2, $ratings['ratings']);
 192  
 193          // Invalid item.
 194          try {
 195              $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'post', 0, 100, '');
 196              $this->fail('Exception expected due invalid itemid.');
 197          } catch (\moodle_exception $e) {
 198              $this->assertEquals('invalidrecord', $e->errorcode);
 199          }
 200  
 201          // Invalid area.
 202          try {
 203              $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'xyz', $this->post->id, 100, '');
 204              $this->fail('Exception expected due invalid rating area.');
 205          } catch (\moodle_exception $e) {
 206              $this->assertEquals('invalidratingarea', $e->errorcode);
 207          }
 208  
 209          // Invalid context. invalid_parameter_exception.
 210          try {
 211              $ratings = core_rating_external::get_item_ratings('module', 0, 'mod_forum', 'post', $this->post->id, 100, '');
 212              $this->fail('Exception expected due invalid context.');
 213          } catch (\invalid_parameter_exception $e) {
 214              $this->assertEquals('invalidparameter', $e->errorcode);
 215          }
 216  
 217          // Test for groupmode.
 218          set_coursemodule_groupmode($this->forum->cmid, SEPARATEGROUPS);
 219          $group = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
 220          groups_add_member($group, $this->teacher1);
 221  
 222          $this->discussion->groupid = $group->id;
 223          $DB->update_record('forum_discussions', $this->discussion);
 224  
 225          // Error for teacher3 and 2 ratings for teacher1 should be returned.
 226          $this->setUser($this->teacher1);
 227          $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100, '');
 228          // We need to execute the return values cleaning process to simulate the web service server.
 229          $ratings = external_api::clean_returnvalue(core_rating_external::get_item_ratings_returns(), $ratings);
 230          $this->assertCount(2, $ratings['ratings']);
 231  
 232          $this->setUser($this->teacher3);
 233          try {
 234              $ratings = core_rating_external::get_item_ratings('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100, '');
 235              $this->fail('Exception expected due invalid group permissions.');
 236          } catch (\moodle_exception $e) {
 237              $this->assertEquals('noviewrate', $e->errorcode);
 238          }
 239  
 240      }
 241  
 242      /**
 243       * Test add_rating
 244       */
 245      public function test_add_rating() {
 246          $this->setUser($this->teacher1);
 247  
 248          // First rating of 50.
 249          $rating = core_rating_external::add_rating('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100,
 250                                                      50, $this->student1->id, RATING_AGGREGATE_AVERAGE);
 251          // We need to execute the return values cleaning process to simulate the web service server.
 252          $rating = external_api::clean_returnvalue(core_rating_external::add_rating_returns(), $rating);
 253          $this->assertTrue($rating['success']);
 254          $this->assertEquals(50, $rating['aggregate']);
 255          $this->assertEquals(1, $rating['count']);
 256  
 257          // New different rate (it will replace the existing one).
 258          $rating = core_rating_external::add_rating('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100,
 259                                                      100, $this->student1->id, RATING_AGGREGATE_AVERAGE);
 260          $rating = external_api::clean_returnvalue(core_rating_external::add_rating_returns(), $rating);
 261                  $this->assertTrue($rating['success']);
 262          $this->assertEquals(100, $rating['aggregate']);
 263          $this->assertEquals(1, $rating['count']);
 264  
 265          // Rate as other user.
 266          $this->setUser($this->teacher2);
 267          $rating = core_rating_external::add_rating('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100,
 268                                                      50, $this->student1->id, RATING_AGGREGATE_AVERAGE);
 269          $rating = external_api::clean_returnvalue(core_rating_external::add_rating_returns(), $rating);
 270          $this->assertEquals(75, $rating['aggregate']);
 271          $this->assertEquals(2, $rating['count']);
 272  
 273          // Try to rate my own post.
 274          $this->setUser($this->student1);
 275          $this->expectException('moodle_exception');
 276          $this->expectExceptionMessage(get_string('ratepermissiondenied', 'rating'));
 277          $rating = core_rating_external::add_rating('module', $this->forum->cmid, 'mod_forum', 'post', $this->post->id, 100,
 278                                                          100, $this->student1->id, RATING_AGGREGATE_AVERAGE);
 279      }
 280  }