Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

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