Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * The exported_posts builder tests. 19 * 20 * @package mod_forum 21 * @copyright 2019 Ryan Wyllie <ryan@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once (__DIR__ . '/generator_trait.php'); 28 29 /** 30 * The exported_posts builder tests. 31 * 32 * @package mod_forum 33 * @copyright 2019 Ryan Wyllie <ryan@moodle.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class mod_forum_builders_exported_posts_testcase extends advanced_testcase { 37 // Make use of the test generator trait. 38 use mod_forum_tests_generator_trait; 39 40 /** @var \mod_forum\local\builders\exported_posts */ 41 private $builder; 42 43 /** 44 * Set up function for tests. 45 */ 46 public function setUp(): void { 47 // We must clear the subscription caches. This has to be done both before each test, and after in case of other 48 // tests using these functions. 49 \mod_forum\subscriptions::reset_forum_cache(); 50 51 $builderfactory = \mod_forum\local\container::get_builder_factory(); 52 $this->builder = $builderfactory->get_exported_posts_builder(); 53 } 54 55 /** 56 * Tear down function for tests. 57 */ 58 public function tearDown(): void { 59 // We must clear the subscription caches. This has to be done both before each test, and after in case of other 60 // tests using these functions. 61 \mod_forum\subscriptions::reset_forum_cache(); 62 } 63 64 /** 65 * Convert the stdClass values into their proper entity classes. 66 * 67 * @param stdClass[] $forums List of forums 68 * @param stdClass[] $discussions List of discussions 69 * @param stdClass[] $posts List of posts 70 * @return array 71 */ 72 private function convert_to_entities(array $forums, array $discussions, array $posts) { 73 global $DB; 74 $entityfactory = \mod_forum\local\container::get_entity_factory(); 75 76 return [ 77 // Forums. 78 array_map(function($forum) use ($entityfactory, $DB) { 79 $course = $DB->get_record('course', ['id' => $forum->course]); 80 $coursemodule = get_coursemodule_from_instance('forum', $forum->id); 81 $context = context_module::instance($coursemodule->id); 82 return $entityfactory->get_forum_from_stdclass($forum, $context, $coursemodule, $course); 83 }, $forums), 84 // Discussions. 85 array_map(function($discussion) use ($entityfactory) { 86 return $entityfactory->get_discussion_from_stdclass($discussion); 87 }, $discussions), 88 // Posts. 89 array_map(function($post) use ($entityfactory) { 90 return $entityfactory->get_post_from_stdclass($post); 91 }, $posts) 92 ]; 93 } 94 95 /** 96 * Test the build function throws exception if not given all of the forums for 97 * the list of posts. 98 */ 99 public function test_build_throws_exception_on_missing_forums() { 100 $this->resetAfterTest(); 101 102 $datagenerator = $this->getDataGenerator(); 103 $user = $datagenerator->create_user(); 104 $course = $datagenerator->create_course(); 105 $forum1 = $datagenerator->create_module('forum', ['course' => $course->id]); 106 $forum2 = $datagenerator->create_module('forum', ['course' => $course->id]); 107 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user); 108 [$discussion2, $post2] = $this->helper_post_to_forum($forum2, $user); 109 110 [$forums, $discussions, $posts] = $this->convert_to_entities( 111 [$forum1, $forum2], 112 [$discussion1, $discussion2], 113 [$post1, $post2] 114 ); 115 116 $this->expectException('moodle_exception'); 117 $this->builder->build($user, [$forums[0]], $discussions, $posts); 118 } 119 120 /** 121 * Test the build function throws exception if not given all of the discussions for 122 * the list of posts. 123 */ 124 public function test_build_throws_exception_on_missing_discussions() { 125 $this->resetAfterTest(); 126 127 $datagenerator = $this->getDataGenerator(); 128 $user = $datagenerator->create_user(); 129 $course = $datagenerator->create_course(); 130 $forum1 = $datagenerator->create_module('forum', ['course' => $course->id]); 131 $forum2 = $datagenerator->create_module('forum', ['course' => $course->id]); 132 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user); 133 [$discussion2, $post2] = $this->helper_post_to_forum($forum2, $user); 134 135 [$forums, $discussions, $posts] = $this->convert_to_entities( 136 [$forum1, $forum2], 137 [$discussion1, $discussion2], 138 [$post1, $post2] 139 ); 140 141 $this->expectException('moodle_exception'); 142 $this->builder->build($user, $forums, [$discussions[0]], $posts); 143 } 144 145 /** 146 * Test the build function returns the exported posts in the order that the posts are 147 * given. 148 */ 149 public function test_build_returns_posts_in_order() { 150 $this->resetAfterTest(); 151 152 $datagenerator = $this->getDataGenerator(); 153 $user1 = $datagenerator->create_user(); 154 $user2 = $datagenerator->create_user(); 155 $course = $datagenerator->create_course(); 156 $forum1 = $datagenerator->create_module('forum', ['course' => $course->id]); 157 $forum2 = $datagenerator->create_module('forum', ['course' => $course->id]); 158 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 159 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 160 $post3 = $this->helper_reply_to_post($post1, $user1); 161 $post4 = $this->helper_reply_to_post($post1, $user2); 162 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 163 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 164 $post7 = $this->helper_reply_to_post($post2, $user1); 165 $post8 = $this->helper_reply_to_post($post2, $user2); 166 167 [$forums, $discussions, $posts] = $this->convert_to_entities( 168 [$forum1, $forum2], 169 [$discussion1, $discussion2, $discussion3, $discussion4], 170 [$post1, $post2, $post3, $post4, $post5, $post6, $post7, $post8] 171 ); 172 173 // Randomly order the posts. 174 shuffle($posts); 175 176 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 177 178 $expectedpostids = array_map(function($post) { 179 return $post->get_id(); 180 }, $posts); 181 $actualpostids = array_map(function($exportedpost) { 182 return (int) $exportedpost->id; 183 }, $exportedposts); 184 185 $this->assertEquals($expectedpostids, $actualpostids); 186 } 187 188 /** 189 * Test the build function loads authors. 190 */ 191 public function test_build_loads_authors() { 192 $this->resetAfterTest(); 193 194 $datagenerator = $this->getDataGenerator(); 195 $user1 = $datagenerator->create_user(); 196 $user2 = $datagenerator->create_user(); 197 $user3 = $datagenerator->create_user(); 198 $course = $datagenerator->create_course(); 199 $forum1 = $datagenerator->create_module('forum', ['course' => $course->id]); 200 $forum2 = $datagenerator->create_module('forum', ['course' => $course->id]); 201 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 202 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 203 $post3 = $this->helper_reply_to_post($post1, $user1); 204 $post4 = $this->helper_reply_to_post($post1, $user2); 205 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 206 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 207 // These 2 replies from user 3 won't be inlcuded in the export. 208 $post7 = $this->helper_reply_to_post($post2, $user3); 209 $post8 = $this->helper_reply_to_post($post2, $user3); 210 211 [$forums, $discussions, $posts] = $this->convert_to_entities( 212 [$forum1, $forum2], 213 [$discussion1, $discussion2, $discussion3, $discussion4], 214 [$post1, $post2, $post3, $post4, $post5, $post6] 215 ); 216 217 $datagenerator->enrol_user($user1->id, $course->id); 218 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 219 220 // We didn't include any posts from user 3 so we shouldn't see the authors 221 // that match that user. 222 $expectedids = [$user1->id, $user2->id]; 223 $actualids = array_unique(array_map(function($exportedpost) { 224 return (int) $exportedpost->author->id; 225 }, $exportedposts)); 226 227 sort($expectedids); 228 sort($actualids); 229 230 $this->assertEquals($expectedids, $actualids); 231 } 232 233 /** 234 * Test the build function loads attachments. 235 */ 236 public function test_build_loads_attachments() { 237 $this->resetAfterTest(); 238 239 $datagenerator = $this->getDataGenerator(); 240 $user1 = $datagenerator->create_user(); 241 $user2 = $datagenerator->create_user(); 242 $user3 = $datagenerator->create_user(); 243 $course = $datagenerator->create_course(); 244 $forum1 = $datagenerator->create_module('forum', ['course' => $course->id]); 245 $forum2 = $datagenerator->create_module('forum', ['course' => $course->id]); 246 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 247 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 248 $post3 = $this->helper_reply_to_post($post1, $user1); 249 $post4 = $this->helper_reply_to_post($post1, $user2); 250 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 251 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 252 $post7 = $this->helper_reply_to_post($post5, $user3); 253 $post8 = $this->helper_reply_to_post($post5, $user3); 254 $filestorage = get_file_storage(); 255 256 [$forums, $discussions, $posts] = $this->convert_to_entities( 257 [$forum1, $forum2], 258 [$discussion1, $discussion2, $discussion3, $discussion4], 259 [$post1, $post2, $post3, $post4, $post5, $post6, $post7, $post8] 260 ); 261 262 // Add an attachment to a post in forum 1. 263 $attachment1 = $filestorage->create_file_from_string( 264 [ 265 'contextid' => $forums[0]->get_context()->id, 266 'component' => 'mod_forum', 267 'filearea' => 'attachment', 268 'itemid' => $post1->id, 269 'filepath' => '/', 270 'filename' => 'example1.jpg', 271 ], 272 'image contents' 273 ); 274 275 // Add an attachment to a post in forum 2. 276 $attachment2 = $filestorage->create_file_from_string( 277 [ 278 'contextid' => $forums[1]->get_context()->id, 279 'component' => 'mod_forum', 280 'filearea' => 'attachment', 281 'itemid' => $post7->id, 282 'filepath' => '/', 283 'filename' => 'example2.jpg', 284 ], 285 'image contents' 286 ); 287 288 // Enrol the user so that they can see the posts. 289 $datagenerator->enrol_user($user1->id, $course->id); 290 291 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 292 293 $expected = ['example1.jpg', 'example2.jpg']; 294 $actual = array_reduce($exportedposts, function($carry, $exportedpost) { 295 if (!empty($exportedpost->attachments)) { 296 foreach ($exportedpost->attachments as $attachment) { 297 $carry[] = $attachment->filename; 298 } 299 } 300 return $carry; 301 }, []); 302 303 sort($expected); 304 sort($actual); 305 306 $this->assertEquals($expected, $actual); 307 } 308 309 /** 310 * Test the build function loads author groups. 311 */ 312 public function test_build_loads_author_groups() { 313 $this->resetAfterTest(); 314 315 $datagenerator = $this->getDataGenerator(); 316 $user1 = $datagenerator->create_user(); 317 $user2 = $datagenerator->create_user(); 318 $user3 = $datagenerator->create_user(); 319 $course1 = $datagenerator->create_course(); 320 $course2 = $datagenerator->create_course(); 321 $forum1 = $datagenerator->create_module('forum', ['course' => $course1->id]); 322 $forum2 = $datagenerator->create_module('forum', ['course' => $course1->id]); 323 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 324 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 325 $post3 = $this->helper_reply_to_post($post1, $user1); 326 $post4 = $this->helper_reply_to_post($post1, $user2); 327 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 328 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 329 $post7 = $this->helper_reply_to_post($post5, $user3); 330 $post8 = $this->helper_reply_to_post($post5, $user3); 331 332 [$forums, $discussions, $posts] = $this->convert_to_entities( 333 [$forum1, $forum2], 334 [$discussion1, $discussion2, $discussion3, $discussion4], 335 [$post1, $post2, $post3, $post4, $post5, $post6, $post7, $post8] 336 ); 337 338 // Enrol the user so that they can see the posts. 339 $datagenerator->enrol_user($user1->id, $course1->id); 340 $datagenerator->enrol_user($user1->id, $course2->id); 341 $datagenerator->enrol_user($user2->id, $course1->id); 342 $datagenerator->enrol_user($user2->id, $course2->id); 343 $datagenerator->enrol_user($user3->id, $course1->id); 344 $datagenerator->enrol_user($user3->id, $course2->id); 345 346 $group1 = $datagenerator->create_group(['courseid' => $course1->id]); 347 $group2 = $datagenerator->create_group(['courseid' => $course1->id]); 348 // This group shouldn't be included in the results since it's in a different course. 349 $group3 = $datagenerator->create_group(['courseid' => $course2->id]); 350 351 $datagenerator->create_group_member(['userid' => $user1->id, 'groupid' => $group1->id]); 352 $datagenerator->create_group_member(['userid' => $user2->id, 'groupid' => $group1->id]); 353 $datagenerator->create_group_member(['userid' => $user1->id, 'groupid' => $group2->id]); 354 $datagenerator->create_group_member(['userid' => $user1->id, 'groupid' => $group3->id]); 355 356 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 357 358 $expected = [ 359 $user1->id => [$group1->id, $group2->id], 360 $user2->id => [$group1->id], 361 $user3->id => [] 362 ]; 363 $actual = array_reduce($exportedposts, function($carry, $exportedpost) { 364 $author = $exportedpost->author; 365 $authorid = $author->id; 366 367 if (!isset($carry[$authorid])) { 368 $carry[$authorid] = array_map(function($group) { 369 return $group['id']; 370 }, $author->groups); 371 } 372 373 return $carry; 374 }, []); 375 376 $this->assertEquals($expected, $actual); 377 } 378 379 /** 380 * Test the build function loads tags. 381 */ 382 public function test_build_loads_tags() { 383 $this->resetAfterTest(); 384 385 $datagenerator = $this->getDataGenerator(); 386 $user1 = $datagenerator->create_user(); 387 $user2 = $datagenerator->create_user(); 388 $user3 = $datagenerator->create_user(); 389 $course1 = $datagenerator->create_course(); 390 $course2 = $datagenerator->create_course(); 391 $forum1 = $datagenerator->create_module('forum', ['course' => $course1->id]); 392 $forum2 = $datagenerator->create_module('forum', ['course' => $course1->id]); 393 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 394 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 395 $post3 = $this->helper_reply_to_post($post1, $user1); 396 $post4 = $this->helper_reply_to_post($post1, $user2); 397 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 398 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 399 $post7 = $this->helper_reply_to_post($post5, $user3); 400 $post8 = $this->helper_reply_to_post($post5, $user3); 401 402 [$forums, $discussions, $posts] = $this->convert_to_entities( 403 [$forum1, $forum2], 404 [$discussion1, $discussion2, $discussion3, $discussion4], 405 [$post1, $post2, $post3, $post4, $post5, $post6, $post7, $post8] 406 ); 407 408 // Enrol the user so that they can see the posts. 409 $datagenerator->enrol_user($user1->id, $course1->id); 410 $datagenerator->enrol_user($user1->id, $course2->id); 411 $datagenerator->enrol_user($user2->id, $course1->id); 412 $datagenerator->enrol_user($user2->id, $course2->id); 413 $datagenerator->enrol_user($user3->id, $course1->id); 414 $datagenerator->enrol_user($user3->id, $course2->id); 415 416 \core_tag_tag::set_item_tags('mod_forum', 'forum_posts', $post1->id, $forums[0]->get_context(), ['foo', 'bar']); 417 \core_tag_tag::set_item_tags('mod_forum', 'forum_posts', $post4->id, $forums[0]->get_context(), ['foo', 'baz']); 418 \core_tag_tag::set_item_tags('mod_forum', 'forum_posts', $post7->id, $forums[1]->get_context(), ['bip']); 419 420 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 421 422 $expected = [ 423 $post1->id => ['foo', 'bar'], 424 $post4->id => ['foo', 'baz'], 425 $post7->id => ['bip'] 426 ]; 427 $actual = array_reduce($exportedposts, function($carry, $exportedpost) { 428 if (!empty($exportedpost->tags)) { 429 $carry[$exportedpost->id] = array_map(function($tag) { 430 return $tag['displayname']; 431 }, $exportedpost->tags); 432 } 433 434 return $carry; 435 }, []); 436 437 $this->assertEquals($expected, $actual); 438 } 439 440 /** 441 * Test the build function loads read_receipts. 442 */ 443 public function test_build_loads_read_receipts() { 444 $this->resetAfterTest(); 445 446 $datagenerator = $this->getDataGenerator(); 447 $user1 = $datagenerator->create_user(['trackforums' => 1]); 448 $user2 = $datagenerator->create_user(['trackforums' => 0]); 449 $course1 = $datagenerator->create_course(); 450 $course2 = $datagenerator->create_course(); 451 $forum1 = $datagenerator->create_module('forum', ['course' => $course1->id, 'trackingtype' => FORUM_TRACKING_OPTIONAL]); 452 $forum2 = $datagenerator->create_module('forum', ['course' => $course1->id, 'trackingtype' => FORUM_TRACKING_OFF]); 453 [$discussion1, $post1] = $this->helper_post_to_forum($forum1, $user1); 454 [$discussion2, $post2] = $this->helper_post_to_forum($forum1, $user2); 455 $post3 = $this->helper_reply_to_post($post1, $user1); 456 $post4 = $this->helper_reply_to_post($post1, $user2); 457 [$discussion3, $post5] = $this->helper_post_to_forum($forum2, $user1); 458 [$discussion4, $post6] = $this->helper_post_to_forum($forum2, $user2); 459 $post7 = $this->helper_reply_to_post($post5, $user1); 460 $post8 = $this->helper_reply_to_post($post5, $user1); 461 462 [$forums, $discussions, $posts] = $this->convert_to_entities( 463 [$forum1, $forum2], 464 [$discussion1, $discussion2, $discussion3, $discussion4], 465 [$post1, $post2, $post3, $post4, $post5, $post6, $post7, $post8] 466 ); 467 468 // Enrol the user so that they can see the posts. 469 $datagenerator->enrol_user($user1->id, $course1->id); 470 $datagenerator->enrol_user($user1->id, $course2->id); 471 $datagenerator->enrol_user($user2->id, $course1->id); 472 $datagenerator->enrol_user($user2->id, $course2->id); 473 474 forum_tp_add_read_record($user1->id, $post1->id); 475 forum_tp_add_read_record($user1->id, $post4->id); 476 forum_tp_add_read_record($user1->id, $post7->id); 477 forum_tp_add_read_record($user2->id, $post1->id); 478 forum_tp_add_read_record($user2->id, $post4->id); 479 forum_tp_add_read_record($user2->id, $post7->id); 480 481 // User 1 has tracking enabled. 482 $exportedposts = $this->builder->build($user1, $forums, $discussions, $posts); 483 484 $expected = [ 485 // Tracking set for forum 1 for user 1. 486 $post1->id => false, 487 $post2->id => true, 488 $post3->id => true, 489 $post4->id => false, 490 // Tracking is off for forum 2 so everything should be null. 491 $post5->id => null, 492 $post6->id => null, 493 $post7->id => null, 494 $post8->id => null 495 ]; 496 $actual = array_reduce($exportedposts, function($carry, $exportedpost) { 497 $carry[$exportedpost->id] = $exportedpost->unread; 498 return $carry; 499 }, []); 500 501 $this->assertEquals($expected, $actual); 502 503 // User 2 has tracking disabled. 504 $exportedposts = $this->builder->build($user2, $forums, $discussions, $posts); 505 506 // Tracking is off for user 2 so everything should be null. 507 $expected = [ 508 $post1->id => null, 509 $post2->id => null, 510 $post3->id => null, 511 $post4->id => null, 512 $post5->id => null, 513 $post6->id => null, 514 $post7->id => null, 515 $post8->id => null 516 ]; 517 $actual = array_reduce($exportedposts, function($carry, $exportedpost) { 518 $carry[$exportedpost->id] = $exportedpost->unread; 519 return $carry; 520 }, []); 521 522 $this->assertEquals($expected, $actual); 523 } 524 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body