78c21b0f1b6570632341ea24ab7e511ae913ca05
[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 = array_values($this->vault->get_from_discussion_ids($user, [$discussion1->id], false));
186         usort($entities, function($a, $b) {
187             return $a <=> $b;
188         });
189         $this->assertCount(3, $entities);
190         $this->assertEquals($post1->id, $entities[0]->get_id());
191         $this->assertEquals($post2->id, $entities[1]->get_id());
192         $this->assertEquals($post3->id, $entities[2]->get_id());
194         $entities = array_values($this->vault->get_from_discussion_ids($user, [$discussion1->id, $discussion2->id], false));
195         usort($entities, function($a, $b) {
196             return $a <=> $b;
197         });
198         $this->assertCount(4, $entities);
199         $this->assertEquals($post1->id, $entities[0]->get_id());
200         $this->assertEquals($post2->id, $entities[1]->get_id());
201         $this->assertEquals($post3->id, $entities[2]->get_id());
202         $this->assertEquals($post4->id, $entities[3]->get_id());
203     }
205     /**
206      * Ensure that selecting posts in a discussion only returns posts that the user can see, when considering private
207      * replies.
208      *
209      * @covers ::get_from_discussion_ids
210      * @covers ::<!public>
211      */
212     public function test_get_from_discussion_ids_private_replies() {
213         $this->resetAfterTest();
215         $course = $this->getDataGenerator()->create_course();
216         $forum = $this->getDataGenerator()->create_module('forum', [
217             'course' => $course->id,
218         ]);
220         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
221         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
222         [$discussion, $post] = $this->helper_post_to_forum($forum, $teacher);
223         $reply = $this->helper_post_to_discussion($forum, $discussion, $teacher, [
224                 'privatereplyto' => $student->id,
225             ]);
226         [$otherdiscussion, $otherpost] = $this->helper_post_to_forum($forum, $teacher);
228         // The user is the author.
229         $entities = array_values($this->vault->get_from_discussion_ids($teacher, [$discussion->id, $otherdiscussion->id], true));
230         $this->assertCount(3, $entities);
231         $this->assertEquals($post->id, $entities[0]->get_id());
232         $this->assertEquals($reply->id, $entities[1]->get_id());
233         $this->assertEquals($otherpost->id, $entities[2]->get_id());
235         // The user is the intended recipient.
236         $entities = array_values($this->vault->get_from_discussion_ids($student, [$discussion->id, $otherdiscussion->id], false));
237         $this->assertCount(3, $entities);
238         $this->assertEquals($post->id, $entities[0]->get_id());
239         $this->assertEquals($reply->id, $entities[1]->get_id());
240         $this->assertEquals($otherpost->id, $entities[2]->get_id());
242         // The user is another teacher..
243         $entities = array_values(
244             $this->vault->get_from_discussion_ids($otherteacher, [$discussion->id, $otherdiscussion->id], true));
245         $this->assertCount(3, $entities);
246         $this->assertEquals($post->id, $entities[0]->get_id());
247         $this->assertEquals($reply->id, $entities[1]->get_id());
248         $this->assertEquals($otherpost->id, $entities[2]->get_id());
250         // The user is a different student.
251         $entities = array_values(
252             $this->vault->get_from_discussion_ids($otherstudent, [$discussion->id, $otherdiscussion->id], false));
253         $this->assertCount(2, $entities);
254         $this->assertEquals($post->id, $entities[0]->get_id());
255         $this->assertEquals($otherpost->id, $entities[1]->get_id());
256     }
258     /**
259      * Test get_replies_to_post.
260      *
261      * @covers ::get_replies_to_post
262      * @covers ::<!public>
263      */
264     public function test_get_replies_to_post() {
265         $this->resetAfterTest();
267         $datagenerator = $this->getDataGenerator();
268         $forumgenerator = $datagenerator->get_plugin_generator('mod_forum');
269         $user = $datagenerator->create_user();
270         $course = $datagenerator->create_course();
271         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
272         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
273         // Create a post with the same created time as the parent post to ensure
274         // we've covered every possible scenario.
275         $post2 = $forumgenerator->create_post((object) [
276             'discussion' => $post1->discussion,
277             'parent' => $post1->id,
278             'userid' => $user->id,
279             'mailnow' => 1,
280             'subject' => 'Some subject',
281             'created' => $post1->created
282         ]);
283         $post3 = $this->helper_reply_to_post($post1, $user);
284         $post4 = $this->helper_reply_to_post($post2, $user);
285         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
287         $entityfactory = \mod_forum\local\container::get_entity_factory();
288         $post1 = $entityfactory->get_post_from_stdclass($post1);
289         $post2 = $entityfactory->get_post_from_stdclass($post2);
290         $post3 = $entityfactory->get_post_from_stdclass($post3);
291         $post4 = $entityfactory->get_post_from_stdclass($post4);
293         $entities = $this->vault->get_replies_to_post($user, $post1, false);
294         $this->assertCount(3, $entities);
295         $this->assertEquals($post2->get_id(), $entities[0]->get_id());
296         $this->assertEquals($post3->get_id(), $entities[1]->get_id());
297         $this->assertEquals($post4->get_id(), $entities[2]->get_id());
299         $entities = $this->vault->get_replies_to_post($user, $post2, false);
300         $this->assertCount(1, $entities);
301         $this->assertEquals($post4->get_id(), $entities[0]->get_id());
303         $entities = $this->vault->get_replies_to_post($user, $post3, false);
304         $this->assertCount(0, $entities);
305     }
307     /**
308      * Test get_replies_to_post with private replies.
309      *
310      * @covers ::get_replies_to_post
311      * @covers ::<!public>
312      */
313     public function test_get_replies_to_post_private_replies() {
314         $this->resetAfterTest();
316         $course = $this->getDataGenerator()->create_course();
317         $forum = $this->getDataGenerator()->create_module('forum', [
318             'course' => $course->id,
319         ]);
321         // Generate a structure:
322         // Initial post p [student]
323         // -> Reply pa [otherstudent]
324         // ---> Reply paa [student]
325         // ---> Private Reply pab [teacher]
326         // -> Private Reply pb [teacher]
327         // -> Reply pc [otherstudent]
328         // ---> Reply pca [student]
329         // -----> Reply pcaa [otherstudent]
330         // -------> Private Reply pcaaa [teacher].
332         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
333         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
335         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
337         $pa = $this->helper_reply_to_post($p, $otherstudent);
338         $paa = $this->helper_reply_to_post($pa, $student);
339         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
341         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
343         $pc = $this->helper_reply_to_post($p, $otherteacher);
344         $pca = $this->helper_reply_to_post($pc, $student);
345         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
346         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
348         $entityfactory = \mod_forum\local\container::get_entity_factory();
349         $ep = $entityfactory->get_post_from_stdclass($p);
350         $epa = $entityfactory->get_post_from_stdclass($pa);
351         $epaa = $entityfactory->get_post_from_stdclass($paa);
352         $epab = $entityfactory->get_post_from_stdclass($pab);
353         $epb = $entityfactory->get_post_from_stdclass($pb);
354         $epc = $entityfactory->get_post_from_stdclass($pc);
355         $epca = $entityfactory->get_post_from_stdclass($pca);
356         $epcaa = $entityfactory->get_post_from_stdclass($pcaa);
357         $epcaaa = $entityfactory->get_post_from_stdclass($pcaaa);
359         // As `student`, you should see all public posts, plus all private replies intended for you.
360         $entities = $this->vault->get_replies_to_post($student, $ep, false);
361         $this->assertCount(6, $entities);
362         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
363         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
364         $this->assertEquals($epb->get_id(), $entities[2]->get_id());
365         $this->assertEquals($epc->get_id(), $entities[3]->get_id());
366         $this->assertEquals($epca->get_id(), $entities[4]->get_id());
367         $this->assertEquals($epcaa->get_id(), $entities[5]->get_id());
369         $entities = $this->vault->get_replies_to_post($student, $epa, false);
370         $this->assertCount(1, $entities);
371         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
373         $this->assertEmpty($this->vault->get_replies_to_post($student, $epaa, false));
374         $this->assertEmpty($this->vault->get_replies_to_post($student, $epab, false));
375         $this->assertEmpty($this->vault->get_replies_to_post($student, $epb, false));
376         $this->assertEmpty($this->vault->get_replies_to_post($student, $epcaa, false));
377         $this->assertEmpty($this->vault->get_replies_to_post($student, $epcaaa, false));
379         $entities = $this->vault->get_replies_to_post($student, $epc, false);
380         $this->assertCount(2, $entities);
381         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
382         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
384         // As `otherstudent`, you should see all public posts, plus all private replies intended for you.
385         $entities = $this->vault->get_replies_to_post($otherstudent, $ep, false);
386         $this->assertCount(7, $entities);
387         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
388         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
389         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
390         $this->assertEquals($epc->get_id(), $entities[3]->get_id());
391         $this->assertEquals($epca->get_id(), $entities[4]->get_id());
392         $this->assertEquals($epcaa->get_id(), $entities[5]->get_id());
393         $this->assertEquals($epcaaa->get_id(), $entities[6]->get_id());
395         $entities = $this->vault->get_replies_to_post($otherstudent, $epa, false);
396         $this->assertCount(2, $entities);
397         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
398         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
400         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epaa, false));
401         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epab, false));
402         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epb, false));
403         $this->assertEmpty($this->vault->get_replies_to_post($otherstudent, $epcaaa, false));
405         $entities = $this->vault->get_replies_to_post($otherstudent, $epc, false);
406         $this->assertCount(3, $entities);
407         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
408         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
409         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
411         // The teacher who authored the private replies can see all.
412         $entities = $this->vault->get_replies_to_post($teacher, $ep, true);
413         $this->assertCount(8, $entities);
414         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
415         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
416         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
417         $this->assertEquals($epb->get_id(), $entities[3]->get_id());
418         $this->assertEquals($epc->get_id(), $entities[4]->get_id());
419         $this->assertEquals($epca->get_id(), $entities[5]->get_id());
420         $this->assertEquals($epcaa->get_id(), $entities[6]->get_id());
421         $this->assertEquals($epcaaa->get_id(), $entities[7]->get_id());
423         $entities = $this->vault->get_replies_to_post($teacher, $epa, true);
424         $this->assertCount(2, $entities);
425         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
426         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
428         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epaa, true));
429         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epab, true));
430         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epb, true));
431         $this->assertEmpty($this->vault->get_replies_to_post($teacher, $epcaaa, true));
433         $entities = $this->vault->get_replies_to_post($teacher, $epc, true);
434         $this->assertCount(3, $entities);
435         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
436         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
437         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
439         // Any other teacher can also see all.
440         $entities = $this->vault->get_replies_to_post($otherteacher, $ep, true);
441         $this->assertCount(8, $entities);
442         $this->assertEquals($epa->get_id(), $entities[0]->get_id());
443         $this->assertEquals($epaa->get_id(), $entities[1]->get_id());
444         $this->assertEquals($epab->get_id(), $entities[2]->get_id());
445         $this->assertEquals($epb->get_id(), $entities[3]->get_id());
446         $this->assertEquals($epc->get_id(), $entities[4]->get_id());
447         $this->assertEquals($epca->get_id(), $entities[5]->get_id());
448         $this->assertEquals($epcaa->get_id(), $entities[6]->get_id());
449         $this->assertEquals($epcaaa->get_id(), $entities[7]->get_id());
451         $entities = $this->vault->get_replies_to_post($otherteacher, $epa, true);
452         $this->assertCount(2, $entities);
453         $this->assertEquals($epaa->get_id(), $entities[0]->get_id());
454         $this->assertEquals($epab->get_id(), $entities[1]->get_id());
456         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epaa, true));
457         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epab, true));
458         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epb, true));
459         $this->assertEmpty($this->vault->get_replies_to_post($otherteacher, $epcaaa, true));
461         $entities = $this->vault->get_replies_to_post($otherteacher, $epc, true);
462         $this->assertCount(3, $entities);
463         $this->assertEquals($epca->get_id(), $entities[0]->get_id());
464         $this->assertEquals($epcaa->get_id(), $entities[1]->get_id());
465         $this->assertEquals($epcaaa->get_id(), $entities[2]->get_id());
466     }
468     /**
469      * Test get_reply_count_for_discussion_ids when no discussion ids were provided.
470      *
471      * @covers ::get_reply_count_for_discussion_ids
472      */
473     public function test_get_reply_count_for_discussion_ids_empty() {
474         $this->resetAfterTest();
476         $datagenerator = $this->getDataGenerator();
477         $user = $datagenerator->create_user();
478         $course = $datagenerator->create_course();
479         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
481         $this->assertCount(0, $this->vault->get_reply_count_for_discussion_ids($user, [], false));
482     }
484     /**
485      * Test get_reply_count_for_discussion_ids.
486      *
487      * @covers ::get_reply_count_for_discussion_ids
488      * @covers ::<!public>
489      */
490     public function test_get_reply_count_for_discussion_ids() {
491         $this->resetAfterTest();
493         $datagenerator = $this->getDataGenerator();
494         $user = $datagenerator->create_user();
495         $course = $datagenerator->create_course();
496         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
497         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
498         $post2 = $this->helper_reply_to_post($post1, $user);
499         $post3 = $this->helper_reply_to_post($post1, $user);
500         $post4 = $this->helper_reply_to_post($post2, $user);
501         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
502         $post6 = $this->helper_reply_to_post($post5, $user);
503         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
505         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [$discussion1->id], false);
506         $this->assertCount(1, $counts);
507         $this->assertEquals(3, $counts[$discussion1->id]);
509         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [$discussion1->id, $discussion2->id], false);
510         $this->assertCount(2, $counts);
511         $this->assertEquals(3, $counts[$discussion1->id]);
512         $this->assertEquals(1, $counts[$discussion2->id]);
514         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [
515             $discussion1->id,
516             $discussion2->id,
517             $discussion3->id
518         ], false);
519         $this->assertCount(2, $counts);
520         $this->assertEquals(3, $counts[$discussion1->id]);
521         $this->assertEquals(1, $counts[$discussion2->id]);
523         $counts = $this->vault->get_reply_count_for_discussion_ids($user, [
524             $discussion1->id,
525             $discussion2->id,
526             $discussion3->id,
527             $discussion3->id + 1000
528         ], false);
529         $this->assertCount(2, $counts);
530         $this->assertEquals(3, $counts[$discussion1->id]);
531         $this->assertEquals(1, $counts[$discussion2->id]);
532     }
534     /**
535      * Test get_reply_count_for_discussion_ids.
536      *
537      * @covers ::get_reply_count_for_discussion_ids
538      * @covers ::<!public>
539      */
540     public function test_get_reply_count_for_discussion_ids_private_replies() {
541         $this->resetAfterTest();
543         $course = $this->getDataGenerator()->create_course();
544         $forum = $this->getDataGenerator()->create_module('forum', [
545             'course' => $course->id,
546         ]);
548         // Generate a structure:
549         // Initial post p [student]
550         // -> Reply pa [otherstudent]
551         // ---> Reply paa [student]
552         // ---> Private Reply pab [teacher]
553         // -> Private Reply pb [teacher]
554         // -> Reply pc [otherstudent]
555         // ---> Reply pca [student]
556         // -----> Reply pcaa [otherstudent]
557         // -------> Private Reply pcaaa [teacher].
559         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
560         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
562         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
564         $pa = $this->helper_reply_to_post($p, $otherstudent);
565         $paa = $this->helper_reply_to_post($pa, $student);
566         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
568         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
570         $pc = $this->helper_reply_to_post($p, $otherteacher);
571         $pca = $this->helper_reply_to_post($pc, $student);
572         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
573         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
575         $this->assertEquals([$discussion->id => 6],
576             $this->vault->get_reply_count_for_discussion_ids($student, [$discussion->id], false));
577         $this->assertEquals([$discussion->id => 7],
578             $this->vault->get_reply_count_for_discussion_ids($otherstudent, [$discussion->id], false));
579         $this->assertEquals([$discussion->id => 8],
580             $this->vault->get_reply_count_for_discussion_ids($teacher, [$discussion->id], true));
581         $this->assertEquals([$discussion->id => 8],
582             $this->vault->get_reply_count_for_discussion_ids($otherteacher, [$discussion->id], true));
583     }
585     /**
586      * Test get_reply_count_for_discussion_id.
587      *
588      * @covers ::get_reply_count_for_post_id_in_discussion_id
589      * @covers ::<!public>
590      */
591     public function test_get_reply_count_for_post_id_in_discussion_id() {
592         $this->resetAfterTest();
594         $datagenerator = $this->getDataGenerator();
595         $user = $datagenerator->create_user();
596         $course = $datagenerator->create_course();
597         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
598         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
599         $post2 = $this->helper_reply_to_post($post1, $user);
600         $post3 = $this->helper_reply_to_post($post1, $user);
601         $post4 = $this->helper_reply_to_post($post2, $user);
602         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
603         $post6 = $this->helper_reply_to_post($post5, $user);
604         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
606         $this->assertEquals(3,
607             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post1->id, $discussion1->id, false));
608         $this->assertEquals(1,
609             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post5->id, $discussion2->id, false));
610         $this->assertEquals(0,
611             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post7->id, $discussion3->id, false));
612         $this->assertEquals(0,
613             $this->vault->get_reply_count_for_post_id_in_discussion_id($user, $post7->id + 1000, $discussion3->id, false));
614     }
616     /**
617      * Test get_reply_count_for_post_id_in_discussion_id.
618      *
619      * @covers ::get_reply_count_for_post_id_in_discussion_id
620      * @covers ::<!public>
621      */
622     public function test_get_reply_count_for_post_id_in_discussion_id_private_replies() {
623         $this->resetAfterTest();
625         $course = $this->getDataGenerator()->create_course();
626         $forum = $this->getDataGenerator()->create_module('forum', [
627             'course' => $course->id,
628         ]);
630         // Generate a structure:
631         // Initial post p [student]
632         // -> Reply pa [otherstudent]
633         // ---> Reply paa [student]
634         // ---> Private Reply pab [teacher]
635         // -> Private Reply pb [teacher]
636         // -> Reply pc [otherstudent]
637         // ---> Reply pca [student]
638         // -----> Reply pcaa [otherstudent]
639         // -------> Private Reply pcaaa [teacher].
641         [$student, $otherstudent] = $this->helper_create_users($course, 2, 'student');
642         [$teacher, $otherteacher] = $this->helper_create_users($course, 2, 'teacher');
644         [$discussion, $p] = $this->helper_post_to_forum($forum, $student);
646         $pa = $this->helper_reply_to_post($p, $otherstudent);
647         $paa = $this->helper_reply_to_post($pa, $student);
648         $pab = $this->helper_reply_to_post($pa, $teacher, ['privatereplyto' => $otherstudent->id]);
650         $pb = $this->helper_reply_to_post($p, $teacher, ['privatereplyto' => $student->id]);
652         $pc = $this->helper_reply_to_post($p, $otherteacher);
653         $pca = $this->helper_reply_to_post($pc, $student);
654         $pcaa = $this->helper_reply_to_post($pca, $otherstudent);
655         $pcaaa = $this->helper_reply_to_post($pcaa, $teacher, ['privatereplyto' => $otherstudent->id]);
657         $this->assertEquals(6,
658             $this->vault->get_reply_count_for_post_id_in_discussion_id($student, $p->id, $discussion->id, false));
659         $this->assertEquals(7,
660             $this->vault->get_reply_count_for_post_id_in_discussion_id($otherstudent, $p->id, $discussion->id, false));
661         $this->assertEquals(8,
662             $this->vault->get_reply_count_for_post_id_in_discussion_id($teacher, $p->id, $discussion->id, true));
663         $this->assertEquals(8,
664             $this->vault->get_reply_count_for_post_id_in_discussion_id($otherteacher, $p->id, $discussion->id, true));
665     }
667     /**
668      * Test get_unread_count_for_discussion_ids.
669      *
670      * @covers ::get_unread_count_for_discussion_ids
671      * @covers ::<!public>
672      */
673     public function test_get_unread_count_for_discussion_ids() {
674         global $CFG;
675         $this->resetAfterTest();
677         $datagenerator = $this->getDataGenerator();
678         $user = $datagenerator->create_user();
679         $otheruser = $datagenerator->create_user();
680         $course = $datagenerator->create_course();
681         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
682         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
683         $post2 = $this->helper_reply_to_post($post1, $user);
684         $post3 = $this->helper_reply_to_post($post1, $user);
685         $post4 = $this->helper_reply_to_post($post2, $user);
686         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
687         $post6 = $this->helper_reply_to_post($post5, $user);
689         $modgenerator = $this->getDataGenerator()->get_plugin_generator('mod_forum');
690         $post7 = $modgenerator->create_post((object) [
691             'discussion' => $post5->discussion,
692             'parent' => $post5->id,
693             'userid' => $user->id,
694             'mailnow' => 1,
695             'subject' => 'old post',
696             // Two days ago which makes it an "old post".
697             'modified' => time() - 172800
698         ]);
700         forum_tp_add_read_record($user->id, $post1->id);
701         forum_tp_add_read_record($user->id, $post4->id);
702         $CFG->forum_oldpostdays = 1;
704         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [$discussion1->id], false);
705         $this->assertCount(1, $counts);
706         $this->assertEquals(2, $counts[$discussion1->id]);
708         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [$discussion1->id, $discussion2->id], false);
709         $this->assertCount(2, $counts);
710         $this->assertEquals(2, $counts[$discussion1->id]);
711         $this->assertEquals(2, $counts[$discussion2->id]);
713         $counts = $this->vault->get_unread_count_for_discussion_ids($user, [
714             $discussion1->id,
715             $discussion2->id,
716             $discussion2->id + 1000
717         ], false);
718         $this->assertCount(2, $counts);
719         $this->assertEquals(2, $counts[$discussion1->id]);
720         $this->assertEquals(2, $counts[$discussion2->id]);
722         $counts = $this->vault->get_unread_count_for_discussion_ids($otheruser, [$discussion1->id, $discussion2->id], false);
723         $this->assertCount(2, $counts);
724         $this->assertEquals(4, $counts[$discussion1->id]);
725         $this->assertEquals(2, $counts[$discussion2->id]);
726     }
728     /**
729      * Test get_unread_count_for_discussion_ids when no discussion ids were provided.
730      *
731      * @covers ::get_unread_count_for_discussion_ids
732      */
733     public function test_get_unread_count_for_discussion_ids_empty() {
734         $this->resetAfterTest();
736         $datagenerator = $this->getDataGenerator();
737         $user = $datagenerator->create_user();
738         $course = $datagenerator->create_course();
739         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
741         $this->assertEquals([], $this->vault->get_unread_count_for_discussion_ids($user, [], false));
742     }
744     /**
745      * Test get_latest_post_id_for_discussion_ids.
746      *
747      * @covers ::get_latest_post_id_for_discussion_ids
748      * @covers ::<!public>
749      */
750     public function test_get_latest_post_id_for_discussion_ids() {
751         $this->resetAfterTest();
753         $datagenerator = $this->getDataGenerator();
754         $user = $datagenerator->create_user();
755         $course = $datagenerator->create_course();
756         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
757         [$discussion1, $post1] = $this->helper_post_to_forum($forum, $user);
758         $post2 = $this->helper_reply_to_post($post1, $user);
759         $post3 = $this->helper_reply_to_post($post1, $user);
760         $post4 = $this->helper_reply_to_post($post2, $user);
761         [$discussion2, $post5] = $this->helper_post_to_forum($forum, $user);
762         $post6 = $this->helper_reply_to_post($post5, $user);
763         [$discussion3, $post7] = $this->helper_post_to_forum($forum, $user);
765         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user, [$discussion1->id], false);
766         $this->assertCount(1, $ids);
767         $this->assertEquals($post4->id, $ids[$discussion1->id]);
769         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user,
770             [$discussion1->id, $discussion2->id], false);
771         $this->assertCount(2, $ids);
772         $this->assertEquals($post4->id, $ids[$discussion1->id]);
773         $this->assertEquals($post6->id, $ids[$discussion2->id]);
775         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user,
776             [$discussion1->id, $discussion2->id, $discussion3->id], false);
777         $this->assertCount(3, $ids);
778         $this->assertEquals($post4->id, $ids[$discussion1->id]);
779         $this->assertEquals($post6->id, $ids[$discussion2->id]);
780         $this->assertEquals($post7->id, $ids[$discussion3->id]);
782         $ids = $this->vault->get_latest_post_id_for_discussion_ids($user, [
783             $discussion1->id,
784             $discussion2->id,
785             $discussion3->id,
786             $discussion3->id + 1000
787         ], false);
788         $this->assertCount(3, $ids);
789         $this->assertEquals($post4->id, $ids[$discussion1->id]);
790         $this->assertEquals($post6->id, $ids[$discussion2->id]);
791         $this->assertEquals($post7->id, $ids[$discussion3->id]);
792     }
794     /**
795      * Test get_latest_post_id_for_discussion_ids when no discussion ids were provided.
796      *
797      * @covers ::get_latest_post_id_for_discussion_ids
798      * @covers ::<!public>
799      */
800     public function test_get_latest_post_id_for_discussion_ids_empty() {
801         $this->resetAfterTest();
803         $datagenerator = $this->getDataGenerator();
804         $user = $datagenerator->create_user();
805         $course = $datagenerator->create_course();
806         $forum = $datagenerator->create_module('forum', ['course' => $course->id]);
808         $this->assertEquals([], $this->vault->get_latest_post_id_for_discussion_ids($user, [], false));
809     }