Proyectos de Subversion Moodle

Rev

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