[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/forum/tests/ -> externallib_test.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * The module forums external functions unit tests
  19   *
  20   * @package    mod_forum
  21   * @category   external
  22   * @copyright  2012 Mark Nelson <markn@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  
  30  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  31  
  32  class mod_forum_external_testcase extends externallib_advanced_testcase {
  33  
  34      /**
  35       * Tests set up
  36       */
  37      protected function setUp() {
  38          global $CFG;
  39  
  40          // We must clear the subscription caches. This has to be done both before each test, and after in case of other
  41          // tests using these functions.
  42          \mod_forum\subscriptions::reset_forum_cache();
  43  
  44          require_once($CFG->dirroot . '/mod/forum/externallib.php');
  45      }
  46  
  47      public function tearDown() {
  48          // We must clear the subscription caches. This has to be done both before each test, and after in case of other
  49          // tests using these functions.
  50          \mod_forum\subscriptions::reset_forum_cache();
  51      }
  52  
  53      /**
  54       * Test get forums
  55       */
  56      public function test_mod_forum_get_forums_by_courses() {
  57          global $USER, $CFG, $DB;
  58  
  59          $this->resetAfterTest(true);
  60  
  61          // Create a user.
  62          $user = self::getDataGenerator()->create_user();
  63  
  64          // Set to the user.
  65          self::setUser($user);
  66  
  67          // Create courses to add the modules.
  68          $course1 = self::getDataGenerator()->create_course();
  69          $course2 = self::getDataGenerator()->create_course();
  70  
  71          // First forum.
  72          $record = new stdClass();
  73          $record->introformat = FORMAT_HTML;
  74          $record->course = $course1->id;
  75          $forum1 = self::getDataGenerator()->create_module('forum', $record);
  76  
  77          // Second forum.
  78          $record = new stdClass();
  79          $record->introformat = FORMAT_HTML;
  80          $record->course = $course2->id;
  81          $forum2 = self::getDataGenerator()->create_module('forum', $record);
  82          $forum2->introfiles = [];
  83  
  84          // Add discussions to the forums.
  85          $record = new stdClass();
  86          $record->course = $course1->id;
  87          $record->userid = $user->id;
  88          $record->forum = $forum1->id;
  89          $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
  90          // Expect one discussion.
  91          $forum1->numdiscussions = 1;
  92          $forum1->cancreatediscussions = true;
  93          $forum1->introfiles = [];
  94  
  95          $record = new stdClass();
  96          $record->course = $course2->id;
  97          $record->userid = $user->id;
  98          $record->forum = $forum2->id;
  99          $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 100          $discussion3 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 101          // Expect two discussions.
 102          $forum2->numdiscussions = 2;
 103          // Default limited role, no create discussion capability enabled.
 104          $forum2->cancreatediscussions = false;
 105  
 106          // Check the forum was correctly created.
 107          $this->assertEquals(2, $DB->count_records_select('forum', 'id = :forum1 OR id = :forum2',
 108                  array('forum1' => $forum1->id, 'forum2' => $forum2->id)));
 109  
 110          // Enrol the user in two courses.
 111          // DataGenerator->enrol_user automatically sets a role for the user with the permission mod/form:viewdiscussion.
 112          $this->getDataGenerator()->enrol_user($user->id, $course1->id, null, 'manual');
 113          // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
 114          $enrol = enrol_get_plugin('manual');
 115          $enrolinstances = enrol_get_instances($course2->id, true);
 116          foreach ($enrolinstances as $courseenrolinstance) {
 117              if ($courseenrolinstance->enrol == "manual") {
 118                  $instance2 = $courseenrolinstance;
 119                  break;
 120              }
 121          }
 122          $enrol->enrol_user($instance2, $user->id);
 123  
 124          // Assign capabilities to view forums for forum 2.
 125          $cm2 = get_coursemodule_from_id('forum', $forum2->cmid, 0, false, MUST_EXIST);
 126          $context2 = context_module::instance($cm2->id);
 127          $newrole = create_role('Role 2', 'role2', 'Role 2 description');
 128          $roleid2 = $this->assignUserCapability('mod/forum:viewdiscussion', $context2->id, $newrole);
 129  
 130          // Create what we expect to be returned when querying the two courses.
 131          unset($forum1->displaywordcount);
 132          unset($forum2->displaywordcount);
 133  
 134          $expectedforums = array();
 135          $expectedforums[$forum1->id] = (array) $forum1;
 136          $expectedforums[$forum2->id] = (array) $forum2;
 137  
 138          // Call the external function passing course ids.
 139          $forums = mod_forum_external::get_forums_by_courses(array($course1->id, $course2->id));
 140          $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
 141          $this->assertCount(2, $forums);
 142          foreach ($forums as $forum) {
 143              $this->assertEquals($expectedforums[$forum['id']], $forum);
 144          }
 145  
 146          // Call the external function without passing course id.
 147          $forums = mod_forum_external::get_forums_by_courses();
 148          $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
 149          $this->assertCount(2, $forums);
 150          foreach ($forums as $forum) {
 151              $this->assertEquals($expectedforums[$forum['id']], $forum);
 152          }
 153  
 154          // Unenrol user from second course and alter expected forums.
 155          $enrol->unenrol_user($instance2, $user->id);
 156          unset($expectedforums[$forum2->id]);
 157  
 158          // Call the external function without passing course id.
 159          $forums = mod_forum_external::get_forums_by_courses();
 160          $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
 161          $this->assertCount(1, $forums);
 162          $this->assertEquals($expectedforums[$forum1->id], $forums[0]);
 163          $this->assertTrue($forums[0]['cancreatediscussions']);
 164  
 165          // Change the type of the forum, the user shouldn't be able to add discussions.
 166          $DB->set_field('forum', 'type', 'news', array('id' => $forum1->id));
 167          $forums = mod_forum_external::get_forums_by_courses();
 168          $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
 169          $this->assertFalse($forums[0]['cancreatediscussions']);
 170  
 171          // Call for the second course we unenrolled the user from.
 172          $forums = mod_forum_external::get_forums_by_courses(array($course2->id));
 173          $forums = external_api::clean_returnvalue(mod_forum_external::get_forums_by_courses_returns(), $forums);
 174          $this->assertCount(0, $forums);
 175      }
 176  
 177      /**
 178       * Test get forum posts
 179       */
 180      public function test_mod_forum_get_forum_discussion_posts() {
 181          global $CFG, $PAGE;
 182  
 183          $this->resetAfterTest(true);
 184  
 185          // Set the CFG variable to allow track forums.
 186          $CFG->forum_trackreadposts = true;
 187  
 188          // Create a user who can track forums.
 189          $record = new stdClass();
 190          $record->trackforums = true;
 191          $user1 = self::getDataGenerator()->create_user($record);
 192          // Create a bunch of other users to post.
 193          $user2 = self::getDataGenerator()->create_user();
 194          $user3 = self::getDataGenerator()->create_user();
 195  
 196          // Set the first created user to the test user.
 197          self::setUser($user1);
 198  
 199          // Create course to add the module.
 200          $course1 = self::getDataGenerator()->create_course();
 201  
 202          // Forum with tracking off.
 203          $record = new stdClass();
 204          $record->course = $course1->id;
 205          $record->trackingtype = FORUM_TRACKING_OFF;
 206          $forum1 = self::getDataGenerator()->create_module('forum', $record);
 207          $forum1context = context_module::instance($forum1->cmid);
 208  
 209          // Add discussions to the forums.
 210          $record = new stdClass();
 211          $record->course = $course1->id;
 212          $record->userid = $user1->id;
 213          $record->forum = $forum1->id;
 214          $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 215  
 216          $record = new stdClass();
 217          $record->course = $course1->id;
 218          $record->userid = $user2->id;
 219          $record->forum = $forum1->id;
 220          $discussion2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 221  
 222          // Add 2 replies to the discussion 1 from different users.
 223          $record = new stdClass();
 224          $record->discussion = $discussion1->id;
 225          $record->parent = $discussion1->firstpost;
 226          $record->userid = $user2->id;
 227          $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 228  
 229          $record->parent = $discussion1reply1->id;
 230          $record->userid = $user3->id;
 231          $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 232  
 233          // Enrol the user in the  course.
 234          $enrol = enrol_get_plugin('manual');
 235          // Following line enrol and assign default role id to the user.
 236          // So the user automatically gets mod/forum:viewdiscussion on all forums of the course.
 237          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
 238          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
 239  
 240          // Delete one user, to test that we still receive posts by this user.
 241          delete_user($user3);
 242  
 243          // Create what we expect to be returned when querying the discussion.
 244          $expectedposts = array(
 245              'posts' => array(),
 246              'warnings' => array(),
 247          );
 248  
 249          // User pictures are initially empty, we should get the links once the external function is called.
 250          $expectedposts['posts'][] = array(
 251              'id' => $discussion1reply2->id,
 252              'discussion' => $discussion1reply2->discussion,
 253              'parent' => $discussion1reply2->parent,
 254              'userid' => (int) $discussion1reply2->userid,
 255              'created' => $discussion1reply2->created,
 256              'modified' => $discussion1reply2->modified,
 257              'mailed' => $discussion1reply2->mailed,
 258              'subject' => $discussion1reply2->subject,
 259              'message' => file_rewrite_pluginfile_urls($discussion1reply2->message, 'pluginfile.php',
 260                      $forum1context->id, 'mod_forum', 'post', $discussion1reply2->id),
 261              'messageformat' => 1,   // This value is usually changed by external_format_text() function.
 262              'messagetrust' => $discussion1reply2->messagetrust,
 263              'attachment' => $discussion1reply2->attachment,
 264              'totalscore' => $discussion1reply2->totalscore,
 265              'mailnow' => $discussion1reply2->mailnow,
 266              'children' => array(),
 267              'canreply' => true,
 268              'postread' => false,
 269              'userfullname' => fullname($user3),
 270              'userpictureurl' => ''
 271          );
 272  
 273          $expectedposts['posts'][] = array(
 274              'id' => $discussion1reply1->id,
 275              'discussion' => $discussion1reply1->discussion,
 276              'parent' => $discussion1reply1->parent,
 277              'userid' => (int) $discussion1reply1->userid,
 278              'created' => $discussion1reply1->created,
 279              'modified' => $discussion1reply1->modified,
 280              'mailed' => $discussion1reply1->mailed,
 281              'subject' => $discussion1reply1->subject,
 282              'message' => file_rewrite_pluginfile_urls($discussion1reply1->message, 'pluginfile.php',
 283                      $forum1context->id, 'mod_forum', 'post', $discussion1reply1->id),
 284              'messageformat' => 1,   // This value is usually changed by external_format_text() function.
 285              'messagetrust' => $discussion1reply1->messagetrust,
 286              'attachment' => $discussion1reply1->attachment,
 287              'totalscore' => $discussion1reply1->totalscore,
 288              'mailnow' => $discussion1reply1->mailnow,
 289              'children' => array($discussion1reply2->id),
 290              'canreply' => true,
 291              'postread' => false,
 292              'userfullname' => fullname($user2),
 293              'userpictureurl' => ''
 294          );
 295  
 296          // Test a discussion with two additional posts (total 3 posts).
 297          $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
 298          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 299          $this->assertEquals(3, count($posts['posts']));
 300  
 301          // Generate here the pictures because we need to wait to the external function to init the theme.
 302          $userpicture = new user_picture($user3);
 303          $userpicture->size = 1; // Size f1.
 304          $expectedposts['posts'][0]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
 305  
 306          $userpicture = new user_picture($user2);
 307          $userpicture->size = 1; // Size f1.
 308          $expectedposts['posts'][1]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
 309  
 310          // Unset the initial discussion post.
 311          array_pop($posts['posts']);
 312          $this->assertEquals($expectedposts, $posts);
 313  
 314          // Test discussion without additional posts. There should be only one post (the one created by the discussion).
 315          $posts = mod_forum_external::get_forum_discussion_posts($discussion2->id, 'modified', 'DESC');
 316          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 317          $this->assertEquals(1, count($posts['posts']));
 318  
 319      }
 320  
 321      /**
 322       * Test get forum posts (qanda forum)
 323       */
 324      public function test_mod_forum_get_forum_discussion_posts_qanda() {
 325          global $CFG, $DB;
 326  
 327          $this->resetAfterTest(true);
 328  
 329          $record = new stdClass();
 330          $user1 = self::getDataGenerator()->create_user($record);
 331          $user2 = self::getDataGenerator()->create_user();
 332  
 333          // Set the first created user to the test user.
 334          self::setUser($user1);
 335  
 336          // Create course to add the module.
 337          $course1 = self::getDataGenerator()->create_course();
 338          $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
 339          $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
 340  
 341          // Forum with tracking off.
 342          $record = new stdClass();
 343          $record->course = $course1->id;
 344          $record->type = 'qanda';
 345          $forum1 = self::getDataGenerator()->create_module('forum', $record);
 346          $forum1context = context_module::instance($forum1->cmid);
 347  
 348          // Add discussions to the forums.
 349          $record = new stdClass();
 350          $record->course = $course1->id;
 351          $record->userid = $user2->id;
 352          $record->forum = $forum1->id;
 353          $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 354  
 355          // Add 1 reply (not the actual user).
 356          $record = new stdClass();
 357          $record->discussion = $discussion1->id;
 358          $record->parent = $discussion1->firstpost;
 359          $record->userid = $user2->id;
 360          $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 361  
 362          // We still see only the original post.
 363          $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
 364          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 365          $this->assertEquals(1, count($posts['posts']));
 366  
 367          // Add a new reply, the user is going to be able to see only the original post and their new post.
 368          $record = new stdClass();
 369          $record->discussion = $discussion1->id;
 370          $record->parent = $discussion1->firstpost;
 371          $record->userid = $user1->id;
 372          $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 373  
 374          $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
 375          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 376          $this->assertEquals(2, count($posts['posts']));
 377  
 378          // Now, we can fake the time of the user post, so he can se the rest of the discussion posts.
 379          $discussion1reply2->created -= $CFG->maxeditingtime * 2;
 380          $DB->update_record('forum_posts', $discussion1reply2);
 381  
 382          $posts = mod_forum_external::get_forum_discussion_posts($discussion1->id, 'modified', 'DESC');
 383          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 384          $this->assertEquals(3, count($posts['posts']));
 385      }
 386  
 387      /**
 388       * Test get forum discussions paginated
 389       */
 390      public function test_mod_forum_get_forum_discussions_paginated() {
 391          global $USER, $CFG, $DB, $PAGE;
 392  
 393          $this->resetAfterTest(true);
 394  
 395          // Set the CFG variable to allow track forums.
 396          $CFG->forum_trackreadposts = true;
 397  
 398          // Create a user who can track forums.
 399          $record = new stdClass();
 400          $record->trackforums = true;
 401          $user1 = self::getDataGenerator()->create_user($record);
 402          // Create a bunch of other users to post.
 403          $user2 = self::getDataGenerator()->create_user();
 404          $user3 = self::getDataGenerator()->create_user();
 405          $user4 = self::getDataGenerator()->create_user();
 406  
 407          // Set the first created user to the test user.
 408          self::setUser($user1);
 409  
 410          // Create courses to add the modules.
 411          $course1 = self::getDataGenerator()->create_course();
 412  
 413          // First forum with tracking off.
 414          $record = new stdClass();
 415          $record->course = $course1->id;
 416          $record->trackingtype = FORUM_TRACKING_OFF;
 417          $forum1 = self::getDataGenerator()->create_module('forum', $record);
 418  
 419          // Add discussions to the forums.
 420          $record = new stdClass();
 421          $record->course = $course1->id;
 422          $record->userid = $user1->id;
 423          $record->forum = $forum1->id;
 424          $discussion1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 425  
 426          // Add three replies to the discussion 1 from different users.
 427          $record = new stdClass();
 428          $record->discussion = $discussion1->id;
 429          $record->parent = $discussion1->firstpost;
 430          $record->userid = $user2->id;
 431          $discussion1reply1 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 432  
 433          $record->parent = $discussion1reply1->id;
 434          $record->userid = $user3->id;
 435          $discussion1reply2 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 436  
 437          $record->userid = $user4->id;
 438          $discussion1reply3 = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_post($record);
 439  
 440          // Enrol the user in the first course.
 441          $enrol = enrol_get_plugin('manual');
 442  
 443          // We don't use the dataGenerator as we need to get the $instance2 to unenrol later.
 444          $enrolinstances = enrol_get_instances($course1->id, true);
 445          foreach ($enrolinstances as $courseenrolinstance) {
 446              if ($courseenrolinstance->enrol == "manual") {
 447                  $instance1 = $courseenrolinstance;
 448                  break;
 449              }
 450          }
 451          $enrol->enrol_user($instance1, $user1->id);
 452  
 453          // Delete one user.
 454          delete_user($user4);
 455  
 456          // Assign capabilities to view discussions for forum 1.
 457          $cm = get_coursemodule_from_id('forum', $forum1->cmid, 0, false, MUST_EXIST);
 458          $context = context_module::instance($cm->id);
 459          $newrole = create_role('Role 2', 'role2', 'Role 2 description');
 460          $this->assignUserCapability('mod/forum:viewdiscussion', $context->id, $newrole);
 461  
 462          // Create what we expect to be returned when querying the forums.
 463  
 464          $post1 = $DB->get_record('forum_posts', array('id' => $discussion1->firstpost), '*', MUST_EXIST);
 465  
 466          // User pictures are initially empty, we should get the links once the external function is called.
 467          $expecteddiscussions = array(
 468                  'id' => $discussion1->firstpost,
 469                  'name' => $discussion1->name,
 470                  'groupid' => $discussion1->groupid,
 471                  'timemodified' => $discussion1reply3->created,
 472                  'usermodified' => $discussion1reply3->userid,
 473                  'timestart' => $discussion1->timestart,
 474                  'timeend' => $discussion1->timeend,
 475                  'discussion' => $discussion1->id,
 476                  'parent' => 0,
 477                  'userid' => $discussion1->userid,
 478                  'created' => $post1->created,
 479                  'modified' => $post1->modified,
 480                  'mailed' => $post1->mailed,
 481                  'subject' => $post1->subject,
 482                  'message' => $post1->message,
 483                  'messageformat' => $post1->messageformat,
 484                  'messagetrust' => $post1->messagetrust,
 485                  'attachment' => $post1->attachment,
 486                  'totalscore' => $post1->totalscore,
 487                  'mailnow' => $post1->mailnow,
 488                  'userfullname' => fullname($user1),
 489                  'usermodifiedfullname' => fullname($user4),
 490                  'userpictureurl' => '',
 491                  'usermodifiedpictureurl' => '',
 492                  'numreplies' => 3,
 493                  'numunread' => 0,
 494                  'pinned' => FORUM_DISCUSSION_UNPINNED
 495              );
 496  
 497          // Call the external function passing forum id.
 498          $discussions = mod_forum_external::get_forum_discussions_paginated($forum1->id);
 499          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 500          $expectedreturn = array(
 501              'discussions' => array($expecteddiscussions),
 502              'warnings' => array()
 503          );
 504  
 505          // Wait the theme to be loaded (the external_api call does that) to generate the user profiles.
 506          $userpicture = new user_picture($user1);
 507          $userpicture->size = 1; // Size f1.
 508          $expectedreturn['discussions'][0]['userpictureurl'] = $userpicture->get_url($PAGE)->out(false);
 509  
 510          $userpicture = new user_picture($user4);
 511          $userpicture->size = 1; // Size f1.
 512          $expectedreturn['discussions'][0]['usermodifiedpictureurl'] = $userpicture->get_url($PAGE)->out(false);
 513  
 514          $this->assertEquals($expectedreturn, $discussions);
 515  
 516          // Call without required view discussion capability.
 517          $this->unassignUserCapability('mod/forum:viewdiscussion', $context->id, $newrole);
 518          try {
 519              mod_forum_external::get_forum_discussions_paginated($forum1->id);
 520              $this->fail('Exception expected due to missing capability.');
 521          } catch (moodle_exception $e) {
 522              $this->assertEquals('noviewdiscussionspermission', $e->errorcode);
 523          }
 524  
 525          // Unenrol user from second course.
 526          $enrol->unenrol_user($instance1, $user1->id);
 527  
 528          // Call for the second course we unenrolled the user from, make sure exception thrown.
 529          try {
 530              mod_forum_external::get_forum_discussions_paginated($forum1->id);
 531              $this->fail('Exception expected due to being unenrolled from the course.');
 532          } catch (moodle_exception $e) {
 533              $this->assertEquals('requireloginerror', $e->errorcode);
 534          }
 535      }
 536  
 537      /**
 538       * Test get forum discussions paginated (qanda forums)
 539       */
 540      public function test_mod_forum_get_forum_discussions_paginated_qanda() {
 541  
 542          $this->resetAfterTest(true);
 543  
 544          // Create courses to add the modules.
 545          $course = self::getDataGenerator()->create_course();
 546  
 547          $user1 = self::getDataGenerator()->create_user();
 548          $user2 = self::getDataGenerator()->create_user();
 549  
 550          // First forum with tracking off.
 551          $record = new stdClass();
 552          $record->course = $course->id;
 553          $record->type = 'qanda';
 554          $forum = self::getDataGenerator()->create_module('forum', $record);
 555  
 556          // Add discussions to the forums.
 557          $discussionrecord = new stdClass();
 558          $discussionrecord->course = $course->id;
 559          $discussionrecord->userid = $user2->id;
 560          $discussionrecord->forum = $forum->id;
 561          $discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($discussionrecord);
 562  
 563          self::setAdminUser();
 564          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 565          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 566  
 567          $this->assertCount(1, $discussions['discussions']);
 568          $this->assertCount(0, $discussions['warnings']);
 569  
 570          self::setUser($user1);
 571          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
 572  
 573          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 574          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 575  
 576          $this->assertCount(1, $discussions['discussions']);
 577          $this->assertCount(0, $discussions['warnings']);
 578  
 579      }
 580  
 581      /**
 582       * Test add_discussion_post
 583       */
 584      public function test_add_discussion_post() {
 585          global $CFG;
 586  
 587          $this->resetAfterTest(true);
 588  
 589          $user = self::getDataGenerator()->create_user();
 590          $otheruser = self::getDataGenerator()->create_user();
 591  
 592          self::setAdminUser();
 593  
 594          // Create course to add the module.
 595          $course = self::getDataGenerator()->create_course(array('groupmode' => VISIBLEGROUPS, 'groupmodeforce' => 0));
 596  
 597          // Forum with tracking off.
 598          $record = new stdClass();
 599          $record->course = $course->id;
 600          $forum = self::getDataGenerator()->create_module('forum', $record);
 601          $cm = get_coursemodule_from_id('forum', $forum->cmid, 0, false, MUST_EXIST);
 602          $forumcontext = context_module::instance($forum->cmid);
 603  
 604          // Add discussions to the forums.
 605          $record = new stdClass();
 606          $record->course = $course->id;
 607          $record->userid = $user->id;
 608          $record->forum = $forum->id;
 609          $discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 610  
 611          // Try to post (user not enrolled).
 612          self::setUser($user);
 613          try {
 614              mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
 615              $this->fail('Exception expected due to being unenrolled from the course.');
 616          } catch (moodle_exception $e) {
 617              $this->assertEquals('requireloginerror', $e->errorcode);
 618          }
 619  
 620          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 621          $this->getDataGenerator()->enrol_user($otheruser->id, $course->id);
 622  
 623          $createdpost = mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
 624          $createdpost = external_api::clean_returnvalue(mod_forum_external::add_discussion_post_returns(), $createdpost);
 625  
 626          $posts = mod_forum_external::get_forum_discussion_posts($discussion->id);
 627          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 628          // We receive the discussion and the post.
 629          $this->assertEquals(2, count($posts['posts']));
 630  
 631          $tested = false;
 632          foreach ($posts['posts'] as $thispost) {
 633              if ($createdpost['postid'] == $thispost['id']) {
 634                  $this->assertEquals('some subject', $thispost['subject']);
 635                  $this->assertEquals('some text here...', $thispost['message']);
 636                  $tested = true;
 637              }
 638          }
 639          $this->assertTrue($tested);
 640  
 641          // Test inline and regular attachment in post
 642          // Create a file in a draft area for inline attachments.
 643          $draftidinlineattach = file_get_unused_draft_itemid();
 644          $draftidattach = file_get_unused_draft_itemid();
 645          self::setUser($user);
 646          $usercontext = context_user::instance($user->id);
 647          $filepath = '/';
 648          $filearea = 'draft';
 649          $component = 'user';
 650          $filenameimg = 'shouldbeanimage.txt';
 651          $filerecordinline = array(
 652              'contextid' => $usercontext->id,
 653              'component' => $component,
 654              'filearea'  => $filearea,
 655              'itemid'    => $draftidinlineattach,
 656              'filepath'  => $filepath,
 657              'filename'  => $filenameimg,
 658          );
 659          $fs = get_file_storage();
 660  
 661          // Create a file in a draft area for regular attachments.
 662          $filerecordattach = $filerecordinline;
 663          $attachfilename = 'attachment.txt';
 664          $filerecordattach['filename'] = $attachfilename;
 665          $filerecordattach['itemid'] = $draftidattach;
 666          $fs->create_file_from_string($filerecordinline, 'image contents (not really)');
 667          $fs->create_file_from_string($filerecordattach, 'simple text attachment');
 668  
 669          $options = array(array('name' => 'inlineattachmentsid', 'value' => $draftidinlineattach),
 670                           array('name' => 'attachmentsid', 'value' => $draftidattach));
 671          $dummytext = 'Here is an inline image: <img src="' . $CFG->wwwroot
 672                       . "/draftfile.php/{$usercontext->id}/user/draft/{$draftidinlineattach}/{$filenameimg}"
 673                       . '" alt="inlineimage">.';
 674          $createdpost = mod_forum_external::add_discussion_post($discussion->firstpost, 'new post inline attachment',
 675                                                                 $dummytext, $options);
 676          $createdpost = external_api::clean_returnvalue(mod_forum_external::add_discussion_post_returns(), $createdpost);
 677  
 678          $posts = mod_forum_external::get_forum_discussion_posts($discussion->id);
 679          $posts = external_api::clean_returnvalue(mod_forum_external::get_forum_discussion_posts_returns(), $posts);
 680          // We receive the discussion and the post.
 681          // Can't guarantee order of posts during tests.
 682          $postfound = false;
 683          foreach ($posts['posts'] as $thispost) {
 684              if ($createdpost['postid'] == $thispost['id']) {
 685                  $this->assertEquals($createdpost['postid'], $thispost['id']);
 686                  $this->assertEquals($thispost['attachment'], 1, "There should be a non-inline attachment");
 687                  $this->assertCount(1, $thispost['attachments'], "There should be 1 attachment");
 688                  $this->assertEquals($thispost['attachments'][0]['filename'], $attachfilename, "There should be 1 attachment");
 689                  $this->assertContains('pluginfile.php', $thispost['message']);
 690                  $postfound = true;
 691                  break;
 692              }
 693          }
 694  
 695          $this->assertTrue($postfound);
 696  
 697          // Check not posting in groups the user is not member of.
 698          $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 699          groups_add_member($group->id, $otheruser->id);
 700  
 701          $forum = self::getDataGenerator()->create_module('forum', $record, array('groupmode' => SEPARATEGROUPS));
 702          $record->forum = $forum->id;
 703          $record->userid = $otheruser->id;
 704          $record->groupid = $group->id;
 705          $discussion = self::getDataGenerator()->get_plugin_generator('mod_forum')->create_discussion($record);
 706  
 707          try {
 708              mod_forum_external::add_discussion_post($discussion->firstpost, 'some subject', 'some text here...');
 709              $this->fail('Exception expected due to invalid permissions for posting.');
 710          } catch (moodle_exception $e) {
 711              $this->assertEquals('nopostforum', $e->errorcode);
 712          }
 713  
 714      }
 715  
 716      /*
 717       * Test add_discussion. A basic test since all the API functions are already covered by unit tests.
 718       */
 719      public function test_add_discussion() {
 720          global $CFG, $USER;
 721          $this->resetAfterTest(true);
 722  
 723          // Create courses to add the modules.
 724          $course = self::getDataGenerator()->create_course();
 725  
 726          $user1 = self::getDataGenerator()->create_user();
 727          $user2 = self::getDataGenerator()->create_user();
 728  
 729          // First forum with tracking off.
 730          $record = new stdClass();
 731          $record->course = $course->id;
 732          $record->type = 'news';
 733          $forum = self::getDataGenerator()->create_module('forum', $record);
 734  
 735          self::setUser($user1);
 736          $this->getDataGenerator()->enrol_user($user1->id, $course->id);
 737  
 738          try {
 739              mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...');
 740              $this->fail('Exception expected due to invalid permissions.');
 741          } catch (moodle_exception $e) {
 742              $this->assertEquals('cannotcreatediscussion', $e->errorcode);
 743          }
 744  
 745          self::setAdminUser();
 746          $createddiscussion = mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...');
 747          $createddiscussion = external_api::clean_returnvalue(mod_forum_external::add_discussion_returns(), $createddiscussion);
 748  
 749          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 750          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 751  
 752          $this->assertCount(1, $discussions['discussions']);
 753          $this->assertCount(0, $discussions['warnings']);
 754  
 755          $this->assertEquals($createddiscussion['discussionid'], $discussions['discussions'][0]['discussion']);
 756          $this->assertEquals(-1, $discussions['discussions'][0]['groupid']);
 757          $this->assertEquals('the subject', $discussions['discussions'][0]['subject']);
 758          $this->assertEquals('some text here...', $discussions['discussions'][0]['message']);
 759  
 760          $discussion2pinned = mod_forum_external::add_discussion($forum->id, 'the pinned subject', 'some 2 text here...', -1,
 761                                                                  array('options' => array('name' => 'discussionpinned',
 762                                                                                           'value' => true)));
 763          $discussion3 = mod_forum_external::add_discussion($forum->id, 'the non pinnedsubject', 'some 3 text here...');
 764          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 765          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 766          $this->assertCount(3, $discussions['discussions']);
 767          $this->assertEquals($discussion2pinned['discussionid'], $discussions['discussions'][0]['discussion']);
 768  
 769          // Test inline and regular attachment in new discussion
 770          // Create a file in a draft area for inline attachments.
 771  
 772          $fs = get_file_storage();
 773  
 774          $draftidinlineattach = file_get_unused_draft_itemid();
 775          $draftidattach = file_get_unused_draft_itemid();
 776  
 777          $usercontext = context_user::instance($USER->id);
 778          $filepath = '/';
 779          $filearea = 'draft';
 780          $component = 'user';
 781          $filenameimg = 'shouldbeanimage.txt';
 782          $filerecord = array(
 783              'contextid' => $usercontext->id,
 784              'component' => $component,
 785              'filearea'  => $filearea,
 786              'itemid'    => $draftidinlineattach,
 787              'filepath'  => $filepath,
 788              'filename'  => $filenameimg,
 789          );
 790  
 791          // Create a file in a draft area for regular attachments.
 792          $filerecordattach = $filerecord;
 793          $attachfilename = 'attachment.txt';
 794          $filerecordattach['filename'] = $attachfilename;
 795          $filerecordattach['itemid'] = $draftidattach;
 796          $fs->create_file_from_string($filerecord, 'image contents (not really)');
 797          $fs->create_file_from_string($filerecordattach, 'simple text attachment');
 798  
 799          $dummytext = 'Here is an inline image: <img src="' . $CFG->wwwroot .
 800                      "/draftfile.php/{$usercontext->id}/user/draft/{$draftidinlineattach}/{$filenameimg}" .
 801                      '" alt="inlineimage">.';
 802  
 803          $options = array(array('name' => 'inlineattachmentsid', 'value' => $draftidinlineattach),
 804                           array('name' => 'attachmentsid', 'value' => $draftidattach));
 805          $createddiscussion = mod_forum_external::add_discussion($forum->id, 'the inline attachment subject',
 806                                                                  $dummytext, -1, $options);
 807          $createddiscussion = external_api::clean_returnvalue(mod_forum_external::add_discussion_returns(), $createddiscussion);
 808  
 809          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 810          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 811  
 812          $this->assertCount(4, $discussions['discussions']);
 813          $this->assertCount(0, $createddiscussion['warnings']);
 814          // Can't guarantee order of posts during tests.
 815          $postfound = false;
 816          foreach ($discussions['discussions'] as $thisdiscussion) {
 817              if ($createddiscussion['discussionid'] == $thisdiscussion['discussion']) {
 818                  $this->assertEquals($thisdiscussion['attachment'], 1, "There should be a non-inline attachment");
 819                  $this->assertCount(1, $thisdiscussion['attachments'], "There should be 1 attachment");
 820                  $this->assertEquals($thisdiscussion['attachments'][0]['filename'], $attachfilename, "There should be 1 attachment");
 821                  $this->assertNotContains('draftfile.php', $thisdiscussion['message']);
 822                  $this->assertContains('pluginfile.php', $thisdiscussion['message']);
 823                  $postfound = true;
 824                  break;
 825              }
 826          }
 827  
 828          $this->assertTrue($postfound);
 829      }
 830  
 831      /**
 832       * Test adding discussions in a course with gorups
 833       */
 834      public function test_add_discussion_in_course_with_groups() {
 835          global $CFG;
 836  
 837          $this->resetAfterTest(true);
 838  
 839          // Create course to add the module.
 840          $course = self::getDataGenerator()->create_course(array('groupmode' => VISIBLEGROUPS, 'groupmodeforce' => 0));
 841          $user = self::getDataGenerator()->create_user();
 842          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 843  
 844          // Forum forcing separate gropus.
 845          $record = new stdClass();
 846          $record->course = $course->id;
 847          $forum = self::getDataGenerator()->create_module('forum', $record, array('groupmode' => SEPARATEGROUPS));
 848  
 849          // Try to post (user not enrolled).
 850          self::setUser($user);
 851  
 852          // The user is not enroled in any group, try to post in a forum with separate groups.
 853          try {
 854              mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...');
 855              $this->fail('Exception expected due to invalid group permissions.');
 856          } catch (moodle_exception $e) {
 857              $this->assertEquals('cannotcreatediscussion', $e->errorcode);
 858          }
 859  
 860          try {
 861              mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...', 0);
 862              $this->fail('Exception expected due to invalid group permissions.');
 863          } catch (moodle_exception $e) {
 864              $this->assertEquals('cannotcreatediscussion', $e->errorcode);
 865          }
 866  
 867          // Create a group.
 868          $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 869  
 870          // Try to post in a group the user is not enrolled.
 871          try {
 872              mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...', $group->id);
 873              $this->fail('Exception expected due to invalid group permissions.');
 874          } catch (moodle_exception $e) {
 875              $this->assertEquals('cannotcreatediscussion', $e->errorcode);
 876          }
 877  
 878          // Add the user to a group.
 879          groups_add_member($group->id, $user->id);
 880  
 881          // Try to post in a group the user is not enrolled.
 882          try {
 883              mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...', $group->id + 1);
 884              $this->fail('Exception expected due to invalid group.');
 885          } catch (moodle_exception $e) {
 886              $this->assertEquals('cannotcreatediscussion', $e->errorcode);
 887          }
 888  
 889          // Nost add the discussion using a valid group.
 890          $discussion = mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...', $group->id);
 891          $discussion = external_api::clean_returnvalue(mod_forum_external::add_discussion_returns(), $discussion);
 892  
 893          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 894          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 895  
 896          $this->assertCount(1, $discussions['discussions']);
 897          $this->assertCount(0, $discussions['warnings']);
 898          $this->assertEquals($discussion['discussionid'], $discussions['discussions'][0]['discussion']);
 899          $this->assertEquals($group->id, $discussions['discussions'][0]['groupid']);
 900  
 901          // Now add a discussions without indicating a group. The function should guess the correct group.
 902          $discussion = mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...');
 903          $discussion = external_api::clean_returnvalue(mod_forum_external::add_discussion_returns(), $discussion);
 904  
 905          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 906          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 907  
 908          $this->assertCount(2, $discussions['discussions']);
 909          $this->assertCount(0, $discussions['warnings']);
 910          $this->assertEquals($group->id, $discussions['discussions'][0]['groupid']);
 911          $this->assertEquals($group->id, $discussions['discussions'][1]['groupid']);
 912  
 913          // Enrol the same user in other group.
 914          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 915          groups_add_member($group2->id, $user->id);
 916  
 917          // Now add a discussions without indicating a group. The function should guess the correct group (the first one).
 918          $discussion = mod_forum_external::add_discussion($forum->id, 'the subject', 'some text here...');
 919          $discussion = external_api::clean_returnvalue(mod_forum_external::add_discussion_returns(), $discussion);
 920  
 921          $discussions = mod_forum_external::get_forum_discussions_paginated($forum->id);
 922          $discussions = external_api::clean_returnvalue(mod_forum_external::get_forum_discussions_paginated_returns(), $discussions);
 923  
 924          $this->assertCount(3, $discussions['discussions']);
 925          $this->assertCount(0, $discussions['warnings']);
 926          $this->assertEquals($group->id, $discussions['discussions'][0]['groupid']);
 927          $this->assertEquals($group->id, $discussions['discussions'][1]['groupid']);
 928          $this->assertEquals($group->id, $discussions['discussions'][2]['groupid']);
 929  
 930      }
 931  
 932      /*
 933       * Test can_add_discussion. A basic test since all the API functions are already covered by unit tests.
 934       */
 935      public function test_can_add_discussion() {
 936  
 937          $this->resetAfterTest(true);
 938  
 939          // Create courses to add the modules.
 940          $course = self::getDataGenerator()->create_course();
 941  
 942          $user = self::getDataGenerator()->create_user();
 943  
 944          // First forum with tracking off.
 945          $record = new stdClass();
 946          $record->course = $course->id;
 947          $record->type = 'news';
 948          $forum = self::getDataGenerator()->create_module('forum', $record);
 949  
 950          // User with no permissions to add in a news forum.
 951          self::setUser($user);
 952          $this->getDataGenerator()->enrol_user($user->id, $course->id);
 953  
 954          $result = mod_forum_external::can_add_discussion($forum->id);
 955          $result = external_api::clean_returnvalue(mod_forum_external::can_add_discussion_returns(), $result);
 956          $this->assertFalse($result['status']);
 957  
 958          self::setAdminUser();
 959          $result = mod_forum_external::can_add_discussion($forum->id);
 960          $result = external_api::clean_returnvalue(mod_forum_external::can_add_discussion_returns(), $result);
 961          $this->assertTrue($result['status']);
 962  
 963      }
 964  
 965  }


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