MDL-65071 forum: Add unit tests
[moodle.git] / mod / forum / tests / vaults_post_test.php
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/>.
17 /**
18  * The post vault 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  */
25 defined('MOODLE_INTERNAL') || die();
27 require_once(__DIR__ . '/generator_trait.php');
29 /**
30  * The post vault 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  * @coversDefaultClass \mod_forum\local\vaults\post
36  */
37 class mod_forum_vaults_post_testcase extends advanced_testcase {
38     // Make use of the test generator trait.
39     use mod_forum_tests_generator_trait;
41     /** @var \mod_forum\local\vaults\post */
42     private $vault;
44     /**
45      * Set up function for tests.
46      */
47     public function setUp() {
48         $vaultfactory = \mod_forum\local\container::get_vault_factory();
49         $this->vault = $vaultfactory->get_post_vault();
50     }
52     /**
53      * Teardown for all tests.
54      */
55     public function tearDown() {
56         unset($this->vault);
57     }
59     /**
60      * Test get_from_id.
61      */
62     public function test_get_from_id() {
63         $this->resetAfterTest();
65         $datagenerator = $this->getDataGenerator();
66         $user = $datagenerator->create_user();
67         $course = $datagenerator->create_course();
68         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
69         [$discussion, $post] = $this->helper_post_to_forum($forum, $user);
71         $postentity = $this->vault->get_from_id($post->id);
73         $this->assertEquals($post->id, $postentity->get_id());
74     }
76     /**
77      * Test get_from_discussion_id.
78      *
79      * @covers ::get_from_discussion_id
80      * @covers ::<!public>
81      */
82     public function test_get_from_discussion_id() {
83         $this->resetAfterTest();
85         $datagenerator = $this->getDataGenerator();
86         $user = $datagenerator->create_user();
87         $course = $datagenerator->create_course();
88         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
89         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
90         $post2 = $this->helper_reply_to_post($post1, $user);
91         $post3 = $this->helper_reply_to_post($post1, $user);
92         [$discussion2, $post4] = $this->helper_post_to_forum($forum, $user);
94         $entities = array_values($this->vault->get_from_discussion_id($user, $discussion1->id, false));
96         $this->assertCount(3, $entities);
97         $this->assertEquals($post1->id, $entities[0]->get_id());
98         $this->assertEquals($post2->id, $entities[1]->get_id());
99         $this->assertEquals($post3->id, $entities[2]->get_id());
101         $entities = array_values($this->vault->get_from_discussion_id($user, $discussion1->id + 1000, false));
102         $this->assertCount(0, $entities);
103     }
105     /**
106      * Ensure that selecting posts in a discussion only returns posts that the user can see, when considering private
107      * replies.
108      *
109      * @covers ::get_from_discussion_id
110      * @covers ::<!public>
111      */
112     public function test_get_from_discussion_id_private_replies() {
113         $this->resetAfterTest();
115         $course = $this->getDataGenerator()->create_course();
116         $forum = $this->getDataGenerator()->create_module('forum', [
117             'course' => $course->id,
118         ]);
120         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
121         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
122         [$discussion, $post] = $this->helper_post_to_forum($forum, $teacher);
123         $reply = $this->helper_post_to_discussion($forum, $discussion, $teacher, [
124                 'privatereplyto' => $student->id,
125             ]);
127         // The user is the author.
128         $entities = array_values($this->vault->get_from_discussion_id($teacher, $discussion->id, true));
129         $this->assertCount(2, $entities);
130         $this->assertEquals($post->id, $entities[0]->get_id());
131         $this->assertEquals($reply->id, $entities[1]->get_id());
133         // The user is the intended recipient.
134         $entities = array_values($this->vault->get_from_discussion_id($student, $discussion->id, false));
135         $this->assertCount(2, $entities);
136         $this->assertEquals($post->id, $entities[0]->get_id());
137         $this->assertEquals($reply->id, $entities[1]->get_id());
139         // The user is another teacher..
140         $entities = array_values($this->vault->get_from_discussion_id($otherteacher, $discussion->id, true));
141         $this->assertCount(2, $entities);
142         $this->assertEquals($post->id, $entities[0]->get_id());
143         $this->assertEquals($reply->id, $entities[1]->get_id());
145         // The user is a different student.
146         $entities = array_values($this->vault->get_from_discussion_id($otherstudent, $discussion->id, false));
147         $this->assertCount(1, $entities);
148         $this->assertEquals($post->id, $entities[0]->get_id());
149     }
151     /**
152      * Test get_from_discussion_ids when no discussion ids were provided.
153      *
154      * @covers ::get_from_discussion_ids
155      */
156     public function test_get_from_discussion_ids_empty() {
157         $this->resetAfterTest();
159         $datagenerator = $this->getDataGenerator();
160         $user = $datagenerator->create_user();
161         $course = $datagenerator->create_course();
162         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
164         $this->assertEquals([], $this->vault->get_from_discussion_ids($user, [], false));
165     }
167     /**
168      * Test get_from_discussion_ids.
169      *
170      * @covers ::get_from_discussion_ids
171      * @covers ::<!public>
172      */
173     public function test_get_from_discussion_ids() {
174         $this->resetAfterTest();
176         $datagenerator = $this->getDataGenerator();
177         $user = $datagenerator->create_user();
178         $course = $datagenerator->create_course();
179         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
180         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
181         $post2 = $this->helper_reply_to_post($post1, $user);
182         $post3 = $this->helper_reply_to_post($post1, $user);
183         [$discussion2, $post4] = $this->helper_post_to_forum($forum, $user);
185         $entities = $this->vault->get_from_discussion_ids($user, [$discussion1->id], false);
186         $this->assertCount(3, $entities);
187         $this->assertArrayHasKey($post1->id, $entities); // Order is not guaranteed, so just verify element existence.
188         $this->assertArrayHasKey($post2->id, $entities);
189         $this->assertArrayHasKey($post3->id, $entities);
191         $entities = $this->vault->get_from_discussion_ids($user, [$discussion1->id, $discussion2->id], false);
192         $this->assertCount(4, $entities);
193         $this->assertArrayHasKey($post1->id, $entities); // Order is not guaranteed, so just verify element existence.
194         $this->assertArrayHasKey($post2->id, $entities);
195         $this->assertArrayHasKey($post3->id, $entities);
196         $this->assertArrayHasKey($post4->id, $entities);
197     }
199     /**
200      * Ensure that selecting posts in a discussion only returns posts that the user can see, when considering private
201      * replies.
202      *
203      * @covers ::get_from_discussion_ids
204      * @covers ::<!public>
205      */
206     public function test_get_from_discussion_ids_private_replies() {
207         $this->resetAfterTest();
209         $course = $this->getDataGenerator()->create_course();
210         $forum = $this->getDataGenerator()->create_module('forum', [
211             'course' => $course->id,
212         ]);
214         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
215         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
216         [$discussion, $post] = $this->helper_post_to_forum($forum, $teacher);
217         $reply = $this->helper_post_to_discussion($forum, $discussion, $teacher, [
218                 'privatereplyto' => $student->id,
219             ]);
220         [$otherdiscussion, $otherpost] = $this->helper_post_to_forum($forum, $teacher);
222         // The user is the author.
223         $entities = $this->vault->get_from_discussion_ids($teacher, [$discussion->id, $otherdiscussion->id], true);
224         $this->assertCount(3, $entities);
225         $this->assertArrayHasKey($post->id, $entities); // Order is not guaranteed, so just verify element existence.
226         $this->assertArrayHasKey($reply->id, $entities);
227         $this->assertArrayHasKey($otherpost->id, $entities);
229         // The user is the intended recipient.
230         $entities = $this->vault->get_from_discussion_ids($student, [$discussion->id, $otherdiscussion->id], false);
231         $this->assertCount(3, $entities);
232         $this->assertArrayHasKey($post->id, $entities); // Order is not guaranteed, so just verify element existence.
233         $this->assertArrayHasKey($reply->id, $entities);
234         $this->assertArrayHasKey($otherpost->id, $entities);
236         // The user is another teacher..
237         $entities = $this->vault->get_from_discussion_ids($otherteacher, [$discussion->id, $otherdiscussion->id], true);
238         $this->assertCount(3, $entities);
239         $this->assertArrayHasKey($post->id, $entities); // Order is not guaranteed, so just verify element existence.
240         $this->assertArrayHasKey($reply->id, $entities);
241         $this->assertArrayHasKey($otherpost->id, $entities);
243         // The user is a different student.
244         $entities = $this->vault->get_from_discussion_ids($otherstudent, [$discussion->id, $otherdiscussion->id], false);
245         $this->assertCount(2, $entities);
246         $this->assertArrayHasKey($post->id, $entities); // Order is not guaranteed, so just verify element existence.
247         $this->assertArrayHasKey($otherpost->id, $entities);
248     }
250     /**
251      * Test get_replies_to_post.
252      *
253      * @covers ::get_replies_to_post
254      * @covers ::<!public>
255      */
256     public function test_get_replies_to_post() {
257         $this->resetAfterTest();
259         $datagenerator = $this->getDataGenerator();
260         $forumgenerator = $datagenerator->get_plugin_generator('mod_forum');
261         $user = $datagenerator->create_user();
262         $course = $datagenerator->create_course();
263         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
264         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
265         // Create a post with the same created time as the parent post to ensure
266         // we've covered every possible scenario.
267         $post2 = $forumgenerator->create_post((object) [
268             'discussion' => $post1->discussion,
269             'parent' => $post1->id,
270             'userid' => $user->id,
271             'mailnow' => 1,
272             'subject' => 'Some subject',
273             'created' => $post1->created
274         ]);
275         $post3 = $this->helper_reply_to_post($post1, $user);
276         $post4 = $this->helper_reply_to_post($post2, $user);
277         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
279         $entityfactory = \mod_forum\local\container::get_entity_factory();
280         $post1 = $entityfactory->get_post_from_stdclass($post1);
281         $post2 = $entityfactory->get_post_from_stdclass($post2);
282         $post3 = $entityfactory->get_post_from_stdclass($post3);
283         $post4 = $entityfactory->get_post_from_stdclass($post4);
285         $entities = $this->vault->get_replies_to_post($user, $post1, false);
286         $this->assertCount(3, $entities);
287         $this->assertEquals($post2->get_id(), $entities[0]->get_id());
288         $this->assertEquals($post3->get_id(), $entities[1]->get_id());
289         $this->assertEquals($post4->get_id(), $entities[2]->get_id());
291         $entities = $this->vault->get_replies_to_post($user, $post2, false);
292         $this->assertCount(1, $entities);
293         $this->assertEquals($post4->get_id(), $entities[0]->get_id());
295         $entities = $this->vault->get_replies_to_post($user, $post3, false);
296         $this->assertCount(0, $entities);
297     }
299     /**
300      * Test get_replies_to_post with private replies.
301      *
302      * @covers ::get_replies_to_post
303      * @covers ::<!public>
304      */
305     public function test_get_replies_to_post_private_replies() {
306         $this->resetAfterTest();
308         $course = $this->getDataGenerator()->create_course();
309         $forum = $this->getDataGenerator()->create_module('forum', [
310             'course' => $course->id,
311         ]);
313         // Generate a structure:
314         // Initial post p [student]
315         // -> Reply pa [otherstudent]
316         // ---> Reply paa [student]
317         // ---> Private Reply pab [teacher]
318         // -> Private Reply pb [teacher]
319         // -> Reply pc [otherstudent]
320         // ---> Reply pca [student]
321         // -----> Reply pcaa [otherstudent]
322         // -------> Private Reply pcaaa [teacher].
324         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
325         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
327         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
329         $pa = $this->helper_reply_to_post($p, $otherstudent);
330         $paa = $this->helper_reply_to_post($pa, $student);
331         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
333         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
335         $pc = $this->helper_reply_to_post($p, $otherteacher);
336         $pca = $this->helper_reply_to_post($pc, $student);
337         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
338         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
340         $entityfactory = \mod_forum\local\container::get_entity_factory();
341         $ep = $entityfactory->get_post_from_stdclass($p);
342         $epa = $entityfactory->get_post_from_stdclass($pa);
343         $epaa = $entityfactory->get_post_from_stdclass($paa);
344         $epab = $entityfactory->get_post_from_stdclass($pab);
345         $epb = $entityfactory->get_post_from_stdclass($pb);
346         $epc = $entityfactory->get_post_from_stdclass($pc);
347         $epca = $entityfactory->get_post_from_stdclass($pca);
348         $epcaa = $entityfactory->get_post_from_stdclass($pcaa);
349         $epcaaa = $entityfactory->get_post_from_stdclass($pcaaa);
351         // As `student`, you should see all public posts, plus all private replies intended for you.
352         $entities = $this->vault->get_replies_to_post($student, $ep, false);
353         $this->assertCount(6, $entities);
354         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
355         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
356         $this->assertEquals($epb->get_id(), $entities[2]->get_id());
357         $this->assertEquals($epc->get_id(), $entities[3]->get_id());
358         $this->assertEquals($epca->get_id(), $entities[4]->get_id());
359         $this->assertEquals($epcaa->get_id(), $entities[5]->get_id());
361         $entities = $this->vault->get_replies_to_post($student, $epa, false);
362         $this->assertCount(1, $entities);
363         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
365         $this->assertEmpty($this->vault->get_replies_to_post($student, $epaa, false));
366         $this->assertEmpty($this->vault->get_replies_to_post($student, $epab, false));
367         $this->assertEmpty($this->vault->get_replies_to_post($student, $epb, false));
368         $this->assertEmpty($this->vault->get_replies_to_post($student, $epcaa, false));
369         $this->assertEmpty($this->vault->get_replies_to_post($student, $epcaaa, false));
371         $entities = $this->vault->get_replies_to_post($student, $epc, false);
372         $this->assertCount(2, $entities);
373         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
374         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
376         // As `otherstudent`, you should see all public posts, plus all private replies intended for you.
377         $entities = $this->vault->get_replies_to_post($otherstudent, $ep, false);
378         $this->assertCount(7, $entities);
379         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
380         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
381         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
382         $this->assertEquals($epc->get_id(), $entities[3]->get_id());
383         $this->assertEquals($epca->get_id(), $entities[4]->get_id());
384         $this->assertEquals($epcaa->get_id(), $entities[5]->get_id());
385         $this->assertEquals($epcaaa->get_id(), $entities[6]->get_id());
387         $entities = $this->vault->get_replies_to_post($otherstudent, $epa, false);
388         $this->assertCount(2, $entities);
389         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
390         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
392         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epaa, false));
393         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epab, false));
394         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epb, false));
395         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epcaaa, false));
397         $entities = $this->vault->get_replies_to_post($otherstudent, $epc, false);
398         $this->assertCount(3, $entities);
399         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
400         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
401         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
403         // The teacher who authored the private replies can see all.
404         $entities = $this->vault->get_replies_to_post($teacher, $ep, true);
405         $this->assertCount(8, $entities);
406         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
407         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
408         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
409         $this->assertEquals($epb->get_id(), $entities[3]->get_id());
410         $this->assertEquals($epc->get_id(), $entities[4]->get_id());
411         $this->assertEquals($epca->get_id(), $entities[5]->get_id());
412         $this->assertEquals($epcaa->get_id(), $entities[6]->get_id());
413         $this->assertEquals($epcaaa->get_id(), $entities[7]->get_id());
415         $entities = $this->vault->get_replies_to_post($teacher, $epa, true);
416         $this->assertCount(2, $entities);
417         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
418         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
420         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epaa, true));
421         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epab, true));
422         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epb, true));
423         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epcaaa, true));
425         $entities = $this->vault->get_replies_to_post($teacher, $epc, true);
426         $this->assertCount(3, $entities);
427         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
428         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
429         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
431         // Any other teacher can also see all.
432         $entities = $this->vault->get_replies_to_post($otherteacher, $ep, true);
433         $this->assertCount(8, $entities);
434         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
435         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
436         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
437         $this->assertEquals($epb->get_id(), $entities[3]->get_id());
438         $this->assertEquals($epc->get_id(), $entities[4]->get_id());
439         $this->assertEquals($epca->get_id(), $entities[5]->get_id());
440         $this->assertEquals($epcaa->get_id(), $entities[6]->get_id());
441         $this->assertEquals($epcaaa->get_id(), $entities[7]->get_id());
443         $entities = $this->vault->get_replies_to_post($otherteacher, $epa, true);
444         $this->assertCount(2, $entities);
445         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
446         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
448         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epaa, true));
449         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epab, true));
450         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epb, true));
451         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epcaaa, true));
453         $entities = $this->vault->get_replies_to_post($otherteacher, $epc, true);
454         $this->assertCount(3, $entities);
455         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
456         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
457         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
458     }
460     /**
461      * Test get_reply_count_for_discussion_ids when no discussion ids were provided.
462      *
463      * @covers ::get_reply_count_for_discussion_ids
464      */
465     public function test_get_reply_count_for_discussion_ids_empty() {
466         $this->resetAfterTest();
468         $datagenerator = $this->getDataGenerator();
469         $user = $datagenerator->create_user();
470         $course = $datagenerator->create_course();
471         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
473         $this->assertCount(0, $this->vault->get_reply_count_for_discussion_ids($user, [], false));
474     }
476     /**
477      * Test get_reply_count_for_discussion_ids.
478      *
479      * @covers ::get_reply_count_for_discussion_ids
480      * @covers ::<!public>
481      */
482     public function test_get_reply_count_for_discussion_ids() {
483         $this->resetAfterTest();
485         $datagenerator = $this->getDataGenerator();
486         $user = $datagenerator->create_user();
487         $course = $datagenerator->create_course();
488         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
489         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
490         $post2 = $this->helper_reply_to_post($post1, $user);
491         $post3 = $this->helper_reply_to_post($post1, $user);
492         $post4 = $this->helper_reply_to_post($post2, $user);
493         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
494         $post6 = $this->helper_reply_to_post($post5, $user);
495         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
497         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [$discussion1->id], false);
498         $this->assertCount(1, $counts);
499         $this->assertEquals(3, $counts[$discussion1->id]);
501         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [$discussion1->id, $discussion2->id], false);
502         $this->assertCount(2, $counts);
503         $this->assertEquals(3, $counts[$discussion1->id]);
504         $this->assertEquals(1, $counts[$discussion2->id]);
506         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [
507             $discussion1->id,
508             $discussion2->id,
509             $discussion3->id
510         ], false);
511         $this->assertCount(2, $counts);
512         $this->assertEquals(3, $counts[$discussion1->id]);
513         $this->assertEquals(1, $counts[$discussion2->id]);
515         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [
516             $discussion1->id,
517             $discussion2->id,
518             $discussion3->id,
519             $discussion3->id + 1000
520         ], false);
521         $this->assertCount(2, $counts);
522         $this->assertEquals(3, $counts[$discussion1->id]);
523         $this->assertEquals(1, $counts[$discussion2->id]);
524     }
526     /**
527      * Test get_reply_count_for_discussion_ids.
528      *
529      * @covers ::get_reply_count_for_discussion_ids
530      * @covers ::<!public>
531      */
532     public function test_get_reply_count_for_discussion_ids_private_replies() {
533         $this->resetAfterTest();
535         $course = $this->getDataGenerator()->create_course();
536         $forum = $this->getDataGenerator()->create_module('forum', [
537             'course' => $course->id,
538         ]);
540         // Generate a structure:
541         // Initial post p [student]
542         // -> Reply pa [otherstudent]
543         // ---> Reply paa [student]
544         // ---> Private Reply pab [teacher]
545         // -> Private Reply pb [teacher]
546         // -> Reply pc [otherstudent]
547         // ---> Reply pca [student]
548         // -----> Reply pcaa [otherstudent]
549         // -------> Private Reply pcaaa [teacher].
551         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
552         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
554         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
556         $pa = $this->helper_reply_to_post($p, $otherstudent);
557         $paa = $this->helper_reply_to_post($pa, $student);
558         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
560         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
562         $pc = $this->helper_reply_to_post($p, $otherteacher);
563         $pca = $this->helper_reply_to_post($pc, $student);
564         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
565         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
567         $this->assertEquals([$discussion->id => 6],
568             $this->vault->get_reply_count_for_discussion_ids($student, [$discussion->id], false));
569         $this->assertEquals([$discussion->id => 7],
570             $this->vault->get_reply_count_for_discussion_ids($otherstudent, [$discussion->id], false));
571         $this->assertEquals([$discussion->id => 8],
572             $this->vault->get_reply_count_for_discussion_ids($teacher, [$discussion->id], true));
573         $this->assertEquals([$discussion->id => 8],
574             $this->vault->get_reply_count_for_discussion_ids($otherteacher, [$discussion->id], true));
575     }
577     /**
578      * Test get_reply_count_for_discussion_id.
579      *
580      * @covers ::get_reply_count_for_post_id_in_discussion_id
581      * @covers ::<!public>
582      */
583     public function test_get_reply_count_for_post_id_in_discussion_id() {
584         $this->resetAfterTest();
586         $datagenerator = $this->getDataGenerator();
587         $user = $datagenerator->create_user();
588         $course = $datagenerator->create_course();
589         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
590         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
591         $post2 = $this->helper_reply_to_post($post1, $user);
592         $post3 = $this->helper_reply_to_post($post1, $user);
593         $post4 = $this->helper_reply_to_post($post2, $user);
594         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
595         $post6 = $this->helper_reply_to_post($post5, $user);
596         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
598         $this->assertEquals(3,
599             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post1->id, $discussion1->id, false));
600         $this->assertEquals(1,
601             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post5->id, $discussion2->id, false));
602         $this->assertEquals(0,
603             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post7->id, $discussion3->id, false));
604         $this->assertEquals(0,
605             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post7->id + 1000, $discussion3->id, false));
606     }
608     /**
609      * Test get_reply_count_for_post_id_in_discussion_id.
610      *
611      * @covers ::get_reply_count_for_post_id_in_discussion_id
612      * @covers ::<!public>
613      */
614     public function test_get_reply_count_for_post_id_in_discussion_id_private_replies() {
615         $this->resetAfterTest();
617         $course = $this->getDataGenerator()->create_course();
618         $forum = $this->getDataGenerator()->create_module('forum', [
619             'course' => $course->id,
620         ]);
622         // Generate a structure:
623         // Initial post p [student]
624         // -> Reply pa [otherstudent]
625         // ---> Reply paa [student]
626         // ---> Private Reply pab [teacher]
627         // -> Private Reply pb [teacher]
628         // -> Reply pc [otherstudent]
629         // ---> Reply pca [student]
630         // -----> Reply pcaa [otherstudent]
631         // -------> Private Reply pcaaa [teacher].
633         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
634         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
636         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
638         $pa = $this->helper_reply_to_post($p, $otherstudent);
639         $paa = $this->helper_reply_to_post($pa, $student);
640         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
642         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
644         $pc = $this->helper_reply_to_post($p, $otherteacher);
645         $pca = $this->helper_reply_to_post($pc, $student);
646         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
647         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
649         $this->assertEquals(6,
650             $this->vault->get_reply_count_for_post_id_in_discussion_id($student, $p->id, $discussion->id, false));
651         $this->assertEquals(7,
652             $this->vault->get_reply_count_for_post_id_in_discussion_id($otherstudent, $p->id, $discussion->id, false));
653         $this->assertEquals(8,
654             $this->vault->get_reply_count_for_post_id_in_discussion_id($teacher, $p->id, $discussion->id, true));
655         $this->assertEquals(8,
656             $this->vault->get_reply_count_for_post_id_in_discussion_id($otherteacher, $p->id, $discussion->id, true));
657     }
659     /**
660      * Test get_unread_count_for_discussion_ids.
661      *
662      * @covers ::get_unread_count_for_discussion_ids
663      * @covers ::<!public>
664      */
665     public function test_get_unread_count_for_discussion_ids() {
666         global $CFG;
667         $this->resetAfterTest();
669         $datagenerator = $this->getDataGenerator();
670         $user = $datagenerator->create_user();
671         $otheruser = $datagenerator->create_user();
672         $course = $datagenerator->create_course();
673         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
674         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
675         $post2 = $this->helper_reply_to_post($post1, $user);
676         $post3 = $this->helper_reply_to_post($post1, $user);
677         $post4 = $this->helper_reply_to_post($post2, $user);
678         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
679         $post6 = $this->helper_reply_to_post($post5, $user);
681         $modgenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum');
682         $post7 = $modgenerator->create_post((object) [
683             'discussion' => $post5->discussion,
684             'parent' => $post5->id,
685             'userid' => $user->id,
686             'mailnow' => 1,
687             'subject' => 'old post',
688             // Two days ago which makes it an "old post".
689             'modified' => time() - 172800
690         ]);
692         forum_tp_add_read_record($user->id, $post1->id);
693         forum_tp_add_read_record($user->id, $post4->id);
694         $CFG->forum_oldpostdays = 1;
696         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [$discussion1->id], false);
697         $this->assertCount(1, $counts);
698         $this->assertEquals(2, $counts[$discussion1->id]);
700         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [$discussion1->id, $discussion2->id], false);
701         $this->assertCount(2, $counts);
702         $this->assertEquals(2, $counts[$discussion1->id]);
703         $this->assertEquals(2, $counts[$discussion2->id]);
705         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [
706             $discussion1->id,
707             $discussion2->id,
708             $discussion2->id + 1000
709         ], false);
710         $this->assertCount(2, $counts);
711         $this->assertEquals(2, $counts[$discussion1->id]);
712         $this->assertEquals(2, $counts[$discussion2->id]);
714         $counts = $this->vault->get_unread_count_for_discussion_ids($otheruser, [$discussion1->id, $discussion2->id], false);
715         $this->assertCount(2, $counts);
716         $this->assertEquals(4, $counts[$discussion1->id]);
717         $this->assertEquals(2, $counts[$discussion2->id]);
718     }
720     /**
721      * Test get_unread_count_for_discussion_ids when no discussion ids were provided.
722      *
723      * @covers ::get_unread_count_for_discussion_ids
724      */
725     public function test_get_unread_count_for_discussion_ids_empty() {
726         $this->resetAfterTest();
728         $datagenerator = $this->getDataGenerator();
729         $user = $datagenerator->create_user();
730         $course = $datagenerator->create_course();
731         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
733         $this->assertEquals([], $this->vault->get_unread_count_for_discussion_ids($user, [], false));
734     }
736     /**
737      * Test get_latest_post_id_for_discussion_ids.
738      *
739      * @covers ::get_latest_post_id_for_discussion_ids
740      * @covers ::<!public>
741      */
742     public function test_get_latest_post_id_for_discussion_ids() {
743         $this->resetAfterTest();
745         $datagenerator = $this->getDataGenerator();
746         $user = $datagenerator->create_user();
747         $course = $datagenerator->create_course();
748         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
749         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
750         $post2 = $this->helper_reply_to_post($post1, $user);
751         $post3 = $this->helper_reply_to_post($post1, $user);
752         $post4 = $this->helper_reply_to_post($post2, $user);
753         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
754         $post6 = $this->helper_reply_to_post($post5, $user);
755         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
757         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user, [$discussion1->id], false);
758         $this->assertCount(1, $ids);
759         $this->assertEquals($post4->id, $ids[$discussion1->id]);
761         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user,
762             [$discussion1->id, $discussion2->id], false);
763         $this->assertCount(2, $ids);
764         $this->assertEquals($post4->id, $ids[$discussion1->id]);
765         $this->assertEquals($post6->id, $ids[$discussion2->id]);
767         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user,
768             [$discussion1->id, $discussion2->id, $discussion3->id], false);
769         $this->assertCount(3, $ids);
770         $this->assertEquals($post4->id, $ids[$discussion1->id]);
771         $this->assertEquals($post6->id, $ids[$discussion2->id]);
772         $this->assertEquals($post7->id, $ids[$discussion3->id]);
774         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user, [
775             $discussion1->id,
776             $discussion2->id,
777             $discussion3->id,
778             $discussion3->id + 1000
779         ], false);
780         $this->assertCount(3, $ids);
781         $this->assertEquals($post4->id, $ids[$discussion1->id]);
782         $this->assertEquals($post6->id, $ids[$discussion2->id]);
783         $this->assertEquals($post7->id, $ids[$discussion3->id]);
784     }
786     /**
787      * Test get_latest_post_id_for_discussion_ids when no discussion ids were provided.
788      *
789      * @covers ::get_latest_post_id_for_discussion_ids
790      * @covers ::<!public>
791      */
792     public function test_get_latest_post_id_for_discussion_ids_empty() {
793         $this->resetAfterTest();
795         $datagenerator = $this->getDataGenerator();
796         $user = $datagenerator->create_user();
797         $course = $datagenerator->create_course();
798         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
800         $this->assertEquals([], $this->vault->get_latest_post_id_for_discussion_ids($user, [], false));
801     }
803     /**
804      * Test get_first_post_for_discussion_ids.
805      *
806      * @covers ::get_first_post_for_discussion_ids
807      * @covers ::<!public>
808      */
809     public function test_get_first_post_for_discussion_ids() {
810         $this->resetAfterTest();
812         $datagenerator = $this->getDataGenerator();
813         $user = $datagenerator->create_user();
814         $course = $datagenerator->create_course();
815         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
816         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
817         $post2 = $this->helper_reply_to_post($post1, $user);
818         $post3 = $this->helper_reply_to_post($post1, $user);
819         $post4 = $this->helper_reply_to_post($post2, $user);
820         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
821         $post6 = $this->helper_reply_to_post($post5, $user);
822         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
824         $firstposts = $this->vault->get_first_post_for_discussion_ids([$discussion1->id]);
825         $this->assertCount(1, $firstposts);
826         $this->assertEquals($post1->id, reset($firstposts)->id);
828         $firstposts = $this->vault->get_first_post_for_discussion_ids([$discussion1->id, $discussion2->id]);
829         $this->assertCount(2, $firstposts);
830         $this->assertEquals($post1->id, $firstposts[$post1->id]->id);
831         $this->assertEquals($post5->id, $firstposts[$post5->id]->id);
833         $firstposts = $this->vault->get_first_post_for_discussion_ids([$discussion1->id, $discussion2->id, $discussion3->id]);
834         $this->assertCount(3, $firstposts);
835         $this->assertEquals($post1->id, $firstposts[$post1->id]->id);
836         $this->assertEquals($post5->id, $firstposts[$post5->id]->id);
837         $this->assertEquals($post7->id, $firstposts[$post7->id]->id);
839         $firstposts = $this->vault->get_first_post_for_discussion_ids([
840             $discussion1->id,
841             $discussion2->id,
842             $discussion3->id,
843             $discussion3->id + 1000
844         ]);
845         $this->assertCount(3, $firstposts);
846         $this->assertEquals($post1->id, $firstposts[$post1->id]->id);
847         $this->assertEquals($post5->id, $firstposts[$post5->id]->id);
848         $this->assertEquals($post7->id, $firstposts[$post7->id]->id);
849     }
851     /**
852      * Test get_first_post_for_discussion_ids when no discussion ids were provided.
853      *
854      * @covers ::get_first_post_for_discussion_ids
855      * @covers ::<!public>
856      */
857     public function test_get_first_post_for_discussion_ids_empty() {
858         $this->resetAfterTest();
860         $datagenerator = $this->getDataGenerator();
861         $user = $datagenerator->create_user();
862         $course = $datagenerator->create_course();
863         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
865         $this->assertEquals([], $this->vault->get_first_post_for_discussion_ids([]));
866     }