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/**
18 * received message global search unit tests.
19 *
20 * @package     core
21 * @copyright   2016 Devang Gaur
22 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27global $CFG;
28require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
29
30/**
31 * Provides the unit tests for received messages global search.
32 *
33 * @package     core
34 * @copyright   2016 Devang Gaur
35 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 */
37class message_received_search_testcase extends advanced_testcase {
38
39    /**
40     * @var string Area id
41     */
42    protected $messagereceivedareaid = null;
43
44    /**
45     * Setting up the test environment
46     * @return void
47     */
48    public function setUp() {
49        $this->resetAfterTest(true);
50        set_config('enableglobalsearch', true);
51
52        $this->messagereceivedareaid = \core_search\manager::generate_areaid('core_message', 'message_received');
53
54        // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
55        $search = testable_core_search::instance();
56    }
57
58    /**
59     * Indexing messages contents.
60     *
61     * @return void
62     */
63    public function test_message_received_indexing() {
64
65        // Returns the instance as long as the area is supported.
66        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
67        $this->assertInstanceOf('\core_message\search\message_received', $searcharea);
68
69        $user1 = self::getDataGenerator()->create_user();
70        $user2 = self::getDataGenerator()->create_user();
71
72        $this->preventResetByRollback();
73        $sink = $this->redirectMessages();
74
75        $message = new \core\message\message();
76        $message->courseid = SITEID;
77        $message->userfrom = $user1;
78        $message->userto = $user2;
79        $message->subject = "Test Subject";
80        $message->smallmessage = "Test small messsage";
81        $message->fullmessage = "Test full messsage";
82        $message->fullmessageformat = 0;
83        $message->fullmessagehtml = null;
84        $message->notification = 0;
85        $message->component = "moodle";
86        $message->name = "instantmessage";
87
88        message_send($message);
89
90        $messages = $sink->get_messages();
91
92        $this->assertEquals(1, count($messages));
93
94        // All records.
95        $recordset = $searcharea->get_recordset_by_timestamp(0);
96        $this->assertTrue($recordset->valid());
97        $nrecords = 0;
98        foreach ($recordset as $record) {
99            $this->assertInstanceOf('stdClass', $record);
100            $doc = $searcharea->get_document($record);
101            $this->assertInstanceOf('\core_search\document', $doc);
102            $nrecords++;
103        }
104        // If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
105        $recordset->close();
106        $this->assertEquals(1, $nrecords);
107
108        // The +2 is to prevent race conditions.
109        $recordset = $searcharea->get_recordset_by_timestamp(time() + 2);
110
111        // No new records.
112        $this->assertFalse($recordset->valid());
113        $recordset->close();
114    }
115
116    /**
117     * Indexing messages, with restricted contexts.
118     */
119    public function test_message_received_indexing_contexts() {
120        global $SITE;
121        require_once(__DIR__ . '/search_sent_test.php');
122
123        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
124
125        $user1 = self::getDataGenerator()->create_user();
126        $user2 = self::getDataGenerator()->create_user();
127
128        $this->preventResetByRollback();
129        $sink = $this->redirectMessages();
130
131        // Send first message.
132        $message = new \core\message\message();
133        $message->courseid = SITEID;
134        $message->userfrom = $user1;
135        $message->userto = $user2;
136        $message->subject = 'Test1';
137        $message->smallmessage = 'Test small messsage';
138        $message->fullmessage = 'Test full messsage';
139        $message->fullmessageformat = 0;
140        $message->fullmessagehtml = null;
141        $message->notification = 0;
142        $message->component = 'moodle';
143        $message->name = 'instantmessage';
144        message_send($message);
145
146        // Ensure that ordering by timestamp will return in consistent order.
147        $this->waitForSecond();
148
149        // Send second message in opposite direction.
150        $message = new \core\message\message();
151        $message->courseid = SITEID;
152        $message->userfrom = $user2;
153        $message->userto = $user1;
154        $message->subject = 'Test2';
155        $message->smallmessage = 'Test small messsage';
156        $message->fullmessage = 'Test full messsage';
157        $message->fullmessageformat = 0;
158        $message->fullmessagehtml = null;
159        $message->notification = 0;
160        $message->component = 'moodle';
161        $message->name = 'instantmessage';
162        message_send($message);
163
164        // Test function with null context and system context (same).
165        $rs = $searcharea->get_document_recordset(0, null);
166        $this->assertEquals(['Test1', 'Test2'], message_sent_search_testcase::recordset_to_subjects($rs));
167        $rs = $searcharea->get_document_recordset(0, context_system::instance());
168        $this->assertEquals(['Test1', 'Test2'], message_sent_search_testcase::recordset_to_subjects($rs));
169
170        // Test with user context for each user.
171        $rs = $searcharea->get_document_recordset(0, \context_user::instance($user1->id));
172        $this->assertEquals(['Test2'], message_sent_search_testcase::recordset_to_subjects($rs));
173        $rs = $searcharea->get_document_recordset(0, \context_user::instance($user2->id));
174        $this->assertEquals(['Test1'], message_sent_search_testcase::recordset_to_subjects($rs));
175
176        // Test with a course context (should return null).
177        $this->assertNull($searcharea->get_document_recordset(0,
178                context_course::instance($SITE->id)));
179    }
180
181    /**
182     * Document contents.
183     *
184     * @return void
185     */
186    public function test_message_received_document() {
187
188        // Returns the instance as long as the area is supported.
189        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
190        $this->assertInstanceOf('\core_message\search\message_received', $searcharea);
191
192        $user1 = self::getDataGenerator()->create_user();
193        $user2 = self::getDataGenerator()->create_user();
194
195        $this->preventResetByRollback();
196        $sink = $this->redirectMessages();
197
198        $message = new \core\message\message();
199        $message->courseid = SITEID;
200        $message->userfrom = $user1;
201        $message->userto = $user2;
202        $message->subject = "Test Subject";
203        $message->smallmessage = "Test small messsage";
204        $message->fullmessage = "Test full messsage";
205        $message->fullmessageformat = 0;
206        $message->fullmessagehtml = null;
207        $message->notification = 0;
208        $message->component = "moodle";
209        $message->name = "instantmessage";
210
211        message_send($message);
212
213        $messages = $sink->get_messages();
214        $message = $messages[0];
215
216        $doc = $searcharea->get_document($message);
217        $this->assertInstanceOf('\core_search\document', $doc);
218        $this->assertEquals($message->id, $doc->get('itemid'));
219        $this->assertEquals($this->messagereceivedareaid . '-' . $message->id, $doc->get('id'));
220        $this->assertEquals(SITEID, $doc->get('courseid'));
221        $this->assertEquals($message->useridfrom, $doc->get('userid'));
222        $this->assertEquals($message->useridto, $doc->get('owneruserid'));
223        $this->assertEquals(content_to_text($message->subject, false), $doc->get('title'));
224        $this->assertEquals(content_to_text($message->smallmessage, false), $doc->get('content'));
225    }
226
227    /**
228     * Document accesses.
229     *
230     * @return void
231     */
232    public function test_message_received_access() {
233        global $CFG;
234
235        // Returns the instance as long as the area is supported.
236        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
237
238        $user1 = self::getDataGenerator()->create_user();
239        $user2 = self::getDataGenerator()->create_user();
240        $user3 = self::getDataGenerator()->create_user();
241
242        $this->preventResetByRollback();
243        $sink = $this->redirectMessages();
244
245        $message = new \core\message\message();
246        $message->courseid = SITEID;
247        $message->userfrom = $user1;
248        $message->userto = $user2;
249        $message->subject = "Test Subject";
250        $message->smallmessage = "Test small messsage";
251        $message->fullmessage = "Test full messsage";
252        $message->fullmessageformat = 0;
253        $message->fullmessagehtml = null;
254        $message->notification = 0;
255        $message->component = "moodle";
256        $message->name = "instantmessage";
257
258        $messageid = message_send($message);
259
260        $messages = $sink->get_messages();
261        $message = $messages[0];
262
263        $this->setUser($user1);
264        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
265        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-123));
266
267        $this->setUser($user2);
268        $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($messageid));
269
270        if ($CFG->messaging) {
271            $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($messageid));
272        } else {
273            $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
274        }
275
276        \core_message\api::delete_message($user2->id, $message->id);
277        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($messageid));
278
279        $this->setUser($user3);
280        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
281
282        $this->setGuestUser();
283        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
284
285        $this->setAdminUser();
286        $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
287
288        delete_user($user1);
289
290        $this->setUser($user2);
291        $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($messageid));
292
293    }
294
295    /**
296     * Test received deleted user.
297     * Tests the case where a received message for a deleted user
298     * is attempted to be added to the index.
299     *
300     * @return void
301     */
302    public function test_message_received_deleted_user() {
303
304        // Returns the instance as long as the area is supported.
305        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
306        $this->assertInstanceOf('\core_message\search\message_received', $searcharea);
307
308        $user1 = self::getDataGenerator()->create_user();
309        $user2 = self::getDataGenerator()->create_user();
310
311        $this->preventResetByRollback();
312        $sink = $this->redirectMessages();
313
314        $message = new \core\message\message();
315        $message->courseid = SITEID;
316        $message->userfrom = $user1;
317        $message->userto = $user2;
318        $message->subject = "Test Subject";
319        $message->smallmessage = "Test small messsage";
320        $message->fullmessage = "Test full messsage";
321        $message->fullmessageformat = 0;
322        $message->fullmessagehtml = null;
323        $message->notification = 0;
324        $message->component = "moodle";
325        $message->name = "instantmessage";
326
327        message_send($message);
328
329        $messages = $sink->get_messages();
330        $message = $messages[0];
331
332        // Delete user.
333        delete_user($user2);
334
335        $doc = $searcharea->get_document($message);
336
337        $this->assertFalse($doc);
338    }
339
340    /**
341     * Test document icon.
342     */
343    public function test_get_doc_icon() {
344        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
345
346        $document = $this->getMockBuilder('\core_search\document')
347            ->disableOriginalConstructor()
348            ->getMock();
349
350        $result = $searcharea->get_doc_icon($document);
351
352        $this->assertEquals('t/message', $result->get_name());
353        $this->assertEquals('moodle', $result->get_component());
354    }
355
356    /**
357     * Test assigned search categories.
358     */
359    public function test_get_category_names() {
360        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
361
362        $expected = ['core-users'];
363        $this->assertEquals($expected, $searcharea->get_category_names());
364    }
365}
366