MDL-71919 core_message: Fix unclosed html tags in email notification
[moodle.git] / message / tests / helper_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  * Contains a test class for the message helper.
19  *
20  * @package core_message
21  * @category test
22  * @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
23  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
30 require_once($CFG->dirroot . '/message/tests/messagelib_test.php');
32 /**
33  * Tests for the message helper class.
34  *
35  * @package core_message
36  * @category test
37  * @copyright 2018 Jake Dallimore <jrhdallimore@gmail.com>
38  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class core_message_helper_testcase extends advanced_testcase {
42     public function setUp(): void {
43         $this->resetAfterTest(true);
44     }
46     public function test_get_member_info_ordering() {
47         // Create a conversation with several users.
48         $user1 = self::getDataGenerator()->create_user();
49         $user2 = self::getDataGenerator()->create_user();
50         $user3 = self::getDataGenerator()->create_user();
51         $user4 = self::getDataGenerator()->create_user();
53         \core_message\api::create_conversation(
54             \core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
55             [
56                 $user1->id,
57                 $user2->id,
58                 $user3->id,
59                 $user4->id,
60             ],
61             'Group conversation'
62         );
64         // Verify that the member information comes back in the same order that we specified in the input array.
65         $memberinfo = \core_message\helper::get_member_info($user1->id, [$user3->id, $user4->id, $user2->id]);
66         $this->assertEquals($user3->id, array_shift($memberinfo)->id);
67         $this->assertEquals($user4->id, array_shift($memberinfo)->id);
68         $this->assertEquals($user2->id, array_shift($memberinfo)->id);
69     }
71     /**
72      * Test search_get_user_details returns the correct profile data when $CFG->messagingallusers is disabled.
73      */
74     public function test_search_get_user_details_sitewide_disabled() {
75         global $DB;
76         set_config('messagingallusers', false);
78         // Two students sharing course 1, visible profile within course (no groups).
79         $user1 = $this->getDataGenerator()->create_user();
80         $user2 = $this->getDataGenerator()->create_user();
81         $course1 = $this->getDataGenerator()->create_course((object) ['groupmode' => 0]);
82         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
83         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
85         // A teacher in course 1.
86         $user3 = $this->getDataGenerator()->create_user();
87         $this->getDataGenerator()->enrol_user($user3->id, $course1->id, 'editingteacher');
89         // Two students sharing course 2, separate groups (profiles not visible to one another).
90         // Note: no groups are created here, but separate groups mode alone is enough to restrict profile access.
91         $user4 = $this->getDataGenerator()->create_user();
92         $user5 = $this->getDataGenerator()->create_user();
93         $course2 = $this->getDataGenerator()->create_course((object) ['groupmode' => 1]);
94         $this->getDataGenerator()->enrol_user($user4->id, $course2->id);
95         $this->getDataGenerator()->enrol_user($user5->id, $course2->id);
97         // A teacher in course 2.
98         $user6 = $this->getDataGenerator()->create_user();
99         $this->getDataGenerator()->enrol_user($user6->id, $course2->id, 'editingteacher');
101         // Teacher and course contact in course 3.
102         $user7 = $this->getDataGenerator()->create_user();
103         $course3 = $this->getDataGenerator()->create_course();
104         $this->getDataGenerator()->enrol_user($user7->id, $course3->id, 'editingteacher');
105         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
107         // Make teachers course contacts.
108         set_config('coursecontact', $teacherrole->id);
110         // User 1 should be able to see users within their course, but not course contacts or students in other courses.
111         $this->setUser($user1);
112         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user2)); // Student in same course.
113         $this->assertEmpty(\core_message\helper::search_get_user_details($user4)); // Student in another course.
114         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user3)); // Teacher in same course.
115         $this->assertEmpty(\core_message\helper::search_get_user_details($user7)); // Teacher (course contact) in another course.
117         // User 3 should be able to see the teacher in their own course, but not other students in that course nor course contacts
118         // or students in other courses.
119         $this->setUser($user4);
120         $this->assertEmpty(\core_message\helper::search_get_user_details($user5)); // Student in same course.
121         $this->assertEmpty(\core_message\helper::search_get_user_details($user1)); // Student in another course.
122         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user6)); // Teacher in same course.
123         $this->assertEmpty(\core_message\helper::search_get_user_details($user7)); // Teacher (course contact) in another course.
124     }
126     /**
127      * Test search_get_user_details returns the correct profile data when $CFG->messagingallusers is enabled.
128      */
129     public function test_search_get_user_details_sitewide_enabled() {
130         global $DB;
131         set_config('messagingallusers', true);
133         // Two students sharing course 1, visible profile within course (no groups).
134         $user1 = $this->getDataGenerator()->create_user();
135         $user2 = $this->getDataGenerator()->create_user();
136         $course1 = $this->getDataGenerator()->create_course((object) ['groupmode' => 0]);
137         $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
138         $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
140         // A teacher in course 1.
141         $user3 = $this->getDataGenerator()->create_user();
142         $this->getDataGenerator()->enrol_user($user3->id, $course1->id, 'editingteacher');
144         // Two students sharing course 2, separate groups (profiles not visible to one another).
145         // Note: no groups are created here, but separate groups mode alone is enough to restrict profile access.
146         $user4 = $this->getDataGenerator()->create_user();
147         $user5 = $this->getDataGenerator()->create_user();
148         $course2 = $this->getDataGenerator()->create_course((object) ['groupmode' => 1]);
149         $this->getDataGenerator()->enrol_user($user4->id, $course2->id);
150         $this->getDataGenerator()->enrol_user($user5->id, $course2->id);
152         // A teacher in course 2.
153         $user6 = $this->getDataGenerator()->create_user();
154         $this->getDataGenerator()->enrol_user($user6->id, $course2->id, 'editingteacher');
156         // Teacher and course contact in course 3.
157         $user7 = $this->getDataGenerator()->create_user();
158         $course3 = $this->getDataGenerator()->create_course();
159         $this->getDataGenerator()->enrol_user($user7->id, $course3->id, 'editingteacher');
160         $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
162         // Make teachers course contacts.
163         set_config('coursecontact', $teacherrole->id);
165         // User 1 should be able to see users within their course and course contacts, but not students in other courses.
166         $this->setUser($user1);
167         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user2)); // Student in same course.
168         $this->assertEmpty(\core_message\helper::search_get_user_details($user4)); // Student in another course.
169         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user3)); // Teacher in same course.
170         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user7)); // Teacher (course contact) in another course.
172         // User 3 should be able to see the teacher in their own course, but not other students in that course nor course contacts
173         // or students in other courses.
174         $this->setUser($user4);
175         $this->assertEmpty(\core_message\helper::search_get_user_details($user5)); // Student in same course.
176         $this->assertEmpty(\core_message\helper::search_get_user_details($user1)); // Student in another course.
177         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user6)); // Teacher in same course.
178         $this->assertNotEmpty(\core_message\helper::search_get_user_details($user7)); // Teacher (course contact) in another course.
179     }
181     /**
182      * Test prevent_unclosed_html_tags returns the correct html.
183      *
184      * @dataProvider prevent_unclosed_html_tags_data
185      * @param string $text text to preview unclosed html tags.
186      * @param string $goodhtml html good structured.
187      * @param bool $removebody true if we want to remove tag body.
188      */
189     public function test_prevent_unclosed_html_tags(string $message, string $goodhtml, bool $removebody) {
190         $this->setAdminUser();
192         $html = \core_message\helper::prevent_unclosed_html_tags($message, $removebody);
193         $this->assertSame($goodhtml, $html);
194     }
196     /**
197      * Data provider for the test_prevent_unclosed_html_tags_data tests.
198      *
199      * @return  array
200      */
201     public function prevent_unclosed_html_tags_data(): array {
202         return [
203             'Prevent unclosed html elements' => [
204                 '<h1>Title</h1><p>Paragraph</p><b>Bold', '<h1>Title</h1><p>Paragraph</p><b>Bold</b>', true
205             ],
206             'Prevent unclosed html elements including comments' => [
207                 '<h1>Title</h1><p>Paragraph</p><!-- Comments //--><b>Bold', '<h1>Title</h1><p>Paragraph</p><!-- Comments //--><b>Bold</b>', true
208             ],
209             'Prevent unclosed comments' => ['<h1>Title</h1><p>Paragraph</p><!-- Comments', '<h1>Title</h1><p>Paragraph</p>', true
210             ],
211             'Prevent unclosed html elements without removing tag body' => [
212                 '<body><h2>Title 2</h2><p>Paragraph</p><b>Bold</body>', '<body><h2>Title 2</h2><p>Paragraph</p><b>Bold</b></body>', false
213             ],
214             'Empty html' => [
215                 '', '', false
216             ],
217         ];
218     }