[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |