Merge branch 'MDL-59106_master-fix2' of git://github.com/dmonllao/moodle
[moodle.git] / search / tests / manager_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  * Search manager unit tests.
19  *
20  * @package     core_search
21  * @category    phpunit
22  * @copyright   2015 David Monllao {@link http://www.davidmonllao.com}
23  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once(__DIR__ . '/fixtures/testable_core_search.php');
29 require_once(__DIR__ . '/fixtures/mock_search_area.php');
31 /**
32  * Unit tests for search manager.
33  *
34  * @package     core_search
35  * @category    phpunit
36  * @copyright   2015 David Monllao {@link http://www.davidmonllao.com}
37  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class search_manager_testcase extends advanced_testcase {
41     protected $forumpostareaid = null;
42     protected $mycoursesareaid = null;
44     public function setUp() {
45         $this->forumpostareaid = \core_search\manager::generate_areaid('mod_forum', 'post');
46         $this->mycoursesareaid = \core_search\manager::generate_areaid('core_course', 'mycourse');
47     }
49     public function test_search_enabled() {
51         $this->resetAfterTest();
53         // Disabled by default.
54         $this->assertFalse(\core_search\manager::is_global_search_enabled());
56         set_config('enableglobalsearch', true);
57         $this->assertTrue(\core_search\manager::is_global_search_enabled());
59         set_config('enableglobalsearch', false);
60         $this->assertFalse(\core_search\manager::is_global_search_enabled());
61     }
63     public function test_search_areas() {
64         global $CFG;
66         $this->resetAfterTest();
68         set_config('enableglobalsearch', true);
70         $fakeareaid = \core_search\manager::generate_areaid('mod_unexisting', 'chihuaquita');
72         $searcharea = \core_search\manager::get_search_area($this->forumpostareaid);
73         $this->assertInstanceOf('\core_search\base', $searcharea);
75         $this->assertFalse(\core_search\manager::get_search_area($fakeareaid));
77         $this->assertArrayHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list());
78         $this->assertArrayNotHasKey($fakeareaid, \core_search\manager::get_search_areas_list());
80         // Enabled by default once global search is enabled.
81         $this->assertArrayHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list(true));
83         list($componentname, $varname) = $searcharea->get_config_var_name();
84         set_config($varname . '_enabled', 0, $componentname);
85         \core_search\manager::clear_static();
87         $this->assertArrayNotHasKey('mod_forum', \core_search\manager::get_search_areas_list(true));
89         set_config($varname . '_enabled', 1, $componentname);
91         // Although the result is wrong, we want to check that \core_search\manager::get_search_areas_list returns cached results.
92         $this->assertArrayNotHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list(true));
94         // Now we check the real result.
95         \core_search\manager::clear_static();
96         $this->assertArrayHasKey($this->forumpostareaid, \core_search\manager::get_search_areas_list(true));
97     }
99     public function test_search_config() {
101         $this->resetAfterTest();
103         $search = testable_core_search::instance();
105         // We should test both plugin types and core subsystems. No core subsystems available yet.
106         $searcharea = $search->get_search_area($this->forumpostareaid);
108         list($componentname, $varname) = $searcharea->get_config_var_name();
110         // Just with a couple of vars should be enough.
111         $start = time() - 100;
112         $end = time();
113         set_config($varname . '_indexingstart', $start, $componentname);
114         set_config($varname . '_indexingend', $end, $componentname);
116         $configs = $search->get_areas_config(array($this->forumpostareaid => $searcharea));
117         $this->assertEquals($start, $configs[$this->forumpostareaid]->indexingstart);
118         $this->assertEquals($end, $configs[$this->forumpostareaid]->indexingend);
119         $this->assertEquals(false, $configs[$this->forumpostareaid]->partial);
121         try {
122             $fakeareaid = \core_search\manager::generate_areaid('mod_unexisting', 'chihuaquita');
123             $search->reset_config($fakeareaid);
124             $this->fail('An exception should be triggered if the provided search area does not exist.');
125         } catch (moodle_exception $ex) {
126             $this->assertContains($fakeareaid . ' search area is not available.', $ex->getMessage());
127         }
129         // We clean it all but enabled components.
130         $search->reset_config($this->forumpostareaid);
131         $config = $searcharea->get_config();
132         $this->assertEquals(1, $config[$varname . '_enabled']);
133         $this->assertEquals(0, $config[$varname . '_indexingstart']);
134         $this->assertEquals(0, $config[$varname . '_indexingend']);
135         $this->assertEquals(0, $config[$varname . '_lastindexrun']);
136         $this->assertEquals(0, $config[$varname . '_partial']);
137         // No caching.
138         $configs = $search->get_areas_config(array($this->forumpostareaid => $searcharea));
139         $this->assertEquals(0, $configs[$this->forumpostareaid]->indexingstart);
140         $this->assertEquals(0, $configs[$this->forumpostareaid]->indexingend);
142         set_config($varname . '_indexingstart', $start, $componentname);
143         set_config($varname . '_indexingend', $end, $componentname);
145         // All components config should be reset.
146         $search->reset_config();
147         $this->assertEquals(0, get_config($componentname, $varname . '_indexingstart'));
148         $this->assertEquals(0, get_config($componentname, $varname . '_indexingend'));
149         $this->assertEquals(0, get_config($componentname, $varname . '_lastindexrun'));
150         // No caching.
151         $configs = $search->get_areas_config(array($this->forumpostareaid => $searcharea));
152         $this->assertEquals(0, $configs[$this->forumpostareaid]->indexingstart);
153         $this->assertEquals(0, $configs[$this->forumpostareaid]->indexingend);
154     }
156     /**
157      * Tests the get_last_indexing_duration method in the base area class.
158      */
159     public function test_get_last_indexing_duration() {
160         $this->resetAfterTest();
162         $search = testable_core_search::instance();
164         $searcharea = $search->get_search_area($this->forumpostareaid);
166         // When never indexed, the duration is false.
167         $this->assertSame(false, $searcharea->get_last_indexing_duration());
169         // Set the start/end times.
170         list($componentname, $varname) = $searcharea->get_config_var_name();
171         $start = time() - 100;
172         $end = time();
173         set_config($varname . '_indexingstart', $start, $componentname);
174         set_config($varname . '_indexingend', $end, $componentname);
176         // The duration should now be 100.
177         $this->assertSame(100, $searcharea->get_last_indexing_duration());
178     }
180     /**
181      * Tests that partial indexing works correctly.
182      */
183     public function test_partial_indexing() {
184         global $USER;
186         $this->resetAfterTest();
187         $this->setAdminUser();
189         // Create a course and a forum.
190         $generator = $this->getDataGenerator();
191         $course = $generator->create_course();
192         $forum = $generator->create_module('forum', ['course' => $course->id]);
194         // Index everything up to current. Ensure the course is older than current second so it
195         // definitely doesn't get indexed again next time.
196         $this->waitForSecond();
197         $search = testable_core_search::instance();
198         $search->index(false, 0);
200         $searcharea = $search->get_search_area($this->forumpostareaid);
201         list($componentname, $varname) = $searcharea->get_config_var_name();
202         $this->assertFalse(get_config($componentname, $varname . '_partial'));
204         // Add 3 discussions to the forum.
205         $now = time();
206         $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
207                 'forum' => $forum->id, 'userid' => $USER->id, 'timemodified' => $now,
208                 'name' => 'Frog']);
209         $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
210                 'forum' => $forum->id, 'userid' => $USER->id, 'timemodified' => $now + 1,
211                 'name' => 'Toad']);
212         $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
213                 'forum' => $forum->id, 'userid' => $USER->id, 'timemodified' => $now + 2,
214                 'name' => 'Zombie']);
215         time_sleep_until($now + 3);
217         // Clear the count of added documents.
218         $search->get_engine()->get_and_clear_added_documents();
220         // Make the search engine delay while indexing each document.
221         $search->get_engine()->set_add_delay(1.2);
223         // Index with a limit of 2 seconds - it should index 2 of the documents (after the second
224         // one, it will have taken 2.4 seconds so it will stop).
225         $search->index(false, 2);
226         $added = $search->get_engine()->get_and_clear_added_documents();
227         $this->assertCount(2, $added);
228         $this->assertEquals('Frog', $added[0]->get('title'));
229         $this->assertEquals('Toad', $added[1]->get('title'));
230         $this->assertEquals(1, get_config($componentname, $varname . '_partial'));
232         // Add a label.
233         $generator->create_module('label', ['course' => $course->id, 'intro' => 'Vampire']);
235         // Wait to next second (so as to not reindex the label more than once, as it will now
236         // be timed before the indexing run).
237         $this->waitForSecond();
239         // Next index with 1 second limit should do the label and not the forum - the logic is,
240         // if it spent ages indexing an area last time, do that one last on next run.
241         $search->index(false, 1);
242         $added = $search->get_engine()->get_and_clear_added_documents();
243         $this->assertCount(1, $added);
244         $this->assertEquals('Vampire', $added[0]->get('title'));
246         // Index again with a 2 second limit - it will redo last post for safety (because of other
247         // things possibly having the same time second), and then do the remaining one. (Note:
248         // because it always does more than one second worth of items, it would actually index 2
249         // posts even if the limit were less than 2.)
250         $search->index(false, 2);
251         $added = $search->get_engine()->get_and_clear_added_documents();
252         $this->assertCount(2, $added);
253         $this->assertEquals('Toad', $added[0]->get('title'));
254         $this->assertEquals('Zombie', $added[1]->get('title'));
255         $this->assertFalse(get_config($componentname, $varname . '_partial'));
257         // Index again - there should be nothing to index this time.
258         $search->index(false, 2);
259         $added = $search->get_engine()->get_and_clear_added_documents();
260         $this->assertCount(0, $added);
261         $this->assertFalse(get_config($componentname, $varname . '_partial'));
262     }
264     /**
265      * Tests that documents with modified time in the future are NOT indexed (as this would cause
266      * a problem by preventing it from indexing other documents modified between now and the future
267      * date).
268      */
269     public function test_future_documents() {
270         $this->resetAfterTest();
272         // Create a course and a forum.
273         $generator = $this->getDataGenerator();
274         $course = $generator->create_course();
275         $forum = $generator->create_module('forum', ['course' => $course->id]);
277         // Index everything up to current. Ensure the course is older than current second so it
278         // definitely doesn't get indexed again next time.
279         $this->waitForSecond();
280         $search = testable_core_search::instance();
281         $search->index(false, 0);
282         $search->get_engine()->get_and_clear_added_documents();
284         // Add 2 discussions to the forum, one of which happend just now, but the other is
285         // incorrectly set to the future.
286         $now = time();
287         $userid = get_admin()->id;
288         $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
289                 'forum' => $forum->id, 'userid' => $userid, 'timemodified' => $now,
290                 'name' => 'Frog']);
291         $generator->get_plugin_generator('mod_forum')->create_discussion(['course' => $course->id,
292                 'forum' => $forum->id, 'userid' => $userid, 'timemodified' => $now + 100,
293                 'name' => 'Toad']);
295         // Wait for a second so we're not actually on the same second as the forum post (there's a
296         // 1 second overlap between indexing; it would get indexed in both checks below otherwise).
297         $this->waitForSecond();
299         // Index.
300         $search->index(false);
301         $added = $search->get_engine()->get_and_clear_added_documents();
302         $this->assertCount(1, $added);
303         $this->assertEquals('Frog', $added[0]->get('title'));
305         // Check latest time - it should be the same as $now, not the + 100.
306         $searcharea = $search->get_search_area($this->forumpostareaid);
307         list($componentname, $varname) = $searcharea->get_config_var_name();
308         $this->assertEquals($now, get_config($componentname, $varname . '_lastindexrun'));
310         // Index again - there should be nothing to index this time.
311         $search->index(false);
312         $added = $search->get_engine()->get_and_clear_added_documents();
313         $this->assertCount(0, $added);
314     }
316     /**
317      * Adding this test here as get_areas_user_accesses process is the same, results just depend on the context level.
318      *
319      * @return void
320      */
321     public function test_search_user_accesses() {
322         global $DB;
324         $this->resetAfterTest();
326         $frontpage = $DB->get_record('course', array('id' => SITEID));
327         $course1 = $this->getDataGenerator()->create_course();
328         $course1ctx = context_course::instance($course1->id);
329         $course2 = $this->getDataGenerator()->create_course();
330         $course2ctx = context_course::instance($course2->id);
331         $teacher = $this->getDataGenerator()->create_user();
332         $teacherctx = context_user::instance($teacher->id);
333         $student = $this->getDataGenerator()->create_user();
334         $studentctx = context_user::instance($student->id);
335         $noaccess = $this->getDataGenerator()->create_user();
336         $noaccessctx = context_user::instance($noaccess->id);
337         $this->getDataGenerator()->enrol_user($teacher->id, $course1->id, 'teacher');
338         $this->getDataGenerator()->enrol_user($student->id, $course1->id, 'student');
340         $frontpageforum = $this->getDataGenerator()->create_module('forum', array('course' => $frontpage->id));
341         $forum1 = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id));
342         $forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id));
343         $forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
344         $frontpageforumcontext = context_module::instance($frontpageforum->cmid);
345         $context1 = context_module::instance($forum1->cmid);
346         $context2 = context_module::instance($forum2->cmid);
347         $context3 = context_module::instance($forum3->cmid);
349         $search = testable_core_search::instance();
350         $mockareaid = \core_search\manager::generate_areaid('core_mocksearch', 'mock_search_area');
351         $search->add_core_search_areas();
352         $search->add_search_area($mockareaid, new core_mocksearch\search\mock_search_area());
354         $this->setAdminUser();
355         $this->assertTrue($search->get_areas_user_accesses());
357         $sitectx = \context_course::instance(SITEID);
358         $systemctxid = \context_system::instance()->id;
360         // Can access the frontpage ones.
361         $this->setUser($noaccess);
362         $contexts = $search->get_areas_user_accesses();
363         $this->assertEquals(array($frontpageforumcontext->id => $frontpageforumcontext->id), $contexts[$this->forumpostareaid]);
364         $this->assertEquals(array($sitectx->id => $sitectx->id), $contexts[$this->mycoursesareaid]);
365         $mockctxs = array($noaccessctx->id => $noaccessctx->id, $systemctxid => $systemctxid);
366         $this->assertEquals($mockctxs, $contexts[$mockareaid]);
368         $this->setUser($teacher);
369         $contexts = $search->get_areas_user_accesses();
370         $frontpageandcourse1 = array($frontpageforumcontext->id => $frontpageforumcontext->id, $context1->id => $context1->id,
371             $context2->id => $context2->id);
372         $this->assertEquals($frontpageandcourse1, $contexts[$this->forumpostareaid]);
373         $this->assertEquals(array($sitectx->id => $sitectx->id, $course1ctx->id => $course1ctx->id),
374             $contexts[$this->mycoursesareaid]);
375         $mockctxs = array($teacherctx->id => $teacherctx->id, $systemctxid => $systemctxid);
376         $this->assertEquals($mockctxs, $contexts[$mockareaid]);
378         $this->setUser($student);
379         $contexts = $search->get_areas_user_accesses();
380         $this->assertEquals($frontpageandcourse1, $contexts[$this->forumpostareaid]);
381         $this->assertEquals(array($sitectx->id => $sitectx->id, $course1ctx->id => $course1ctx->id),
382             $contexts[$this->mycoursesareaid]);
383         $mockctxs = array($studentctx->id => $studentctx->id, $systemctxid => $systemctxid);
384         $this->assertEquals($mockctxs, $contexts[$mockareaid]);
386         // Hide the activity.
387         set_coursemodule_visible($forum2->cmid, 0);
388         $contexts = $search->get_areas_user_accesses();
389         $this->assertEquals(array($frontpageforumcontext->id => $frontpageforumcontext->id, $context1->id => $context1->id),
390             $contexts[$this->forumpostareaid]);
392         // Now test course limited searches.
393         set_coursemodule_visible($forum2->cmid, 1);
394         $this->getDataGenerator()->enrol_user($student->id, $course2->id, 'student');
395         $contexts = $search->get_areas_user_accesses();
396         $allcontexts = array($frontpageforumcontext->id => $frontpageforumcontext->id, $context1->id => $context1->id,
397             $context2->id => $context2->id, $context3->id => $context3->id);
398         $this->assertEquals($allcontexts, $contexts[$this->forumpostareaid]);
399         $this->assertEquals(array($sitectx->id => $sitectx->id, $course1ctx->id => $course1ctx->id,
400             $course2ctx->id => $course2ctx->id), $contexts[$this->mycoursesareaid]);
402         $contexts = $search->get_areas_user_accesses(array($course1->id, $course2->id));
403         $allcontexts = array($context1->id => $context1->id, $context2->id => $context2->id, $context3->id => $context3->id);
404         $this->assertEquals($allcontexts, $contexts[$this->forumpostareaid]);
405         $this->assertEquals(array($course1ctx->id => $course1ctx->id,
406             $course2ctx->id => $course2ctx->id), $contexts[$this->mycoursesareaid]);
408         $contexts = $search->get_areas_user_accesses(array($course2->id));
409         $allcontexts = array($context3->id => $context3->id);
410         $this->assertEquals($allcontexts, $contexts[$this->forumpostareaid]);
411         $this->assertEquals(array($course2ctx->id => $course2ctx->id), $contexts[$this->mycoursesareaid]);
413         $contexts = $search->get_areas_user_accesses(array($course1->id));
414         $allcontexts = array($context1->id => $context1->id, $context2->id => $context2->id);
415         $this->assertEquals($allcontexts, $contexts[$this->forumpostareaid]);
416         $this->assertEquals(array($course1ctx->id => $course1ctx->id), $contexts[$this->mycoursesareaid]);
417     }
419     /**
420      * Tests the block support in get_search_user_accesses.
421      *
422      * @return void
423      */
424     public function test_search_user_accesses_blocks() {
425         $this->resetAfterTest();
426         $this->setAdminUser();
428         // Create course and add HTML block.
429         $generator = $this->getDataGenerator();
430         $course1 = $generator->create_course();
431         $context1 = \context_course::instance($course1->id);
432         $page = new \moodle_page();
433         $page->set_context($context1);
434         $page->set_course($course1);
435         $page->set_pagelayout('standard');
436         $page->set_pagetype('course-view');
437         $page->blocks->load_blocks();
438         $page->blocks->add_block_at_end_of_default_region('html');
440         // Create another course with HTML blocks only in some weird page or a module page (not
441         // yet supported, so both these blocks will be ignored).
442         $course2 = $generator->create_course();
443         $context2 = \context_course::instance($course2->id);
444         $page = new \moodle_page();
445         $page->set_context($context2);
446         $page->set_course($course2);
447         $page->set_pagelayout('standard');
448         $page->set_pagetype('bogus-page');
449         $page->blocks->load_blocks();
450         $page->blocks->add_block_at_end_of_default_region('html');
452         $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
453         $forumcontext = context_module::instance($forum->cmid);
454         $page = new \moodle_page();
455         $page->set_context($forumcontext);
456         $page->set_course($course2);
457         $page->set_pagelayout('standard');
458         $page->set_pagetype('mod-forum-view');
459         $page->blocks->load_blocks();
460         $page->blocks->add_block_at_end_of_default_region('html');
462         // The third course has 2 HTML blocks.
463         $course3 = $generator->create_course();
464         $context3 = \context_course::instance($course3->id);
465         $page = new \moodle_page();
466         $page->set_context($context3);
467         $page->set_course($course3);
468         $page->set_pagelayout('standard');
469         $page->set_pagetype('course-view');
470         $page->blocks->load_blocks();
471         $page->blocks->add_block_at_end_of_default_region('html');
472         $page->blocks->add_block_at_end_of_default_region('html');
474         // Student 1 belongs to all 3 courses.
475         $student1 = $generator->create_user();
476         $generator->enrol_user($student1->id, $course1->id, 'student');
477         $generator->enrol_user($student1->id, $course2->id, 'student');
478         $generator->enrol_user($student1->id, $course3->id, 'student');
480         // Student 2 belongs only to course 2.
481         $student2 = $generator->create_user();
482         $generator->enrol_user($student2->id, $course2->id, 'student');
484         // And the third student is only in course 3.
485         $student3 = $generator->create_user();
486         $generator->enrol_user($student3->id, $course3->id, 'student');
488         $search = testable_core_search::instance();
489         $search->add_core_search_areas();
491         // Admin gets 'true' result to function regardless of blocks.
492         $this->setAdminUser();
493         $this->assertTrue($search->get_areas_user_accesses());
495         // Student 1 gets all 3 block contexts.
496         $this->setUser($student1);
497         $contexts = $search->get_areas_user_accesses();
498         $this->assertArrayHasKey('block_html-content', $contexts);
499         $this->assertCount(3, $contexts['block_html-content']);
501         // Student 2 does not get any blocks.
502         $this->setUser($student2);
503         $contexts = $search->get_areas_user_accesses();
504         $this->assertArrayNotHasKey('block_html-content', $contexts);
506         // Student 3 gets only two of them.
507         $this->setUser($student3);
508         $contexts = $search->get_areas_user_accesses();
509         $this->assertArrayHasKey('block_html-content', $contexts);
510         $this->assertCount(2, $contexts['block_html-content']);
512         // A course limited search for student 1 is the same as the student 3 search.
513         $this->setUser($student1);
514         $limitedcontexts = $search->get_areas_user_accesses([$course3->id]);
515         $this->assertEquals($contexts['block_html-content'], $limitedcontexts['block_html-content']);
516     }
518     /**
519      * Test get_areas_user_accesses with regard to the 'all available courses' config option.
520      *
521      * @return void
522      */
523     public function test_search_user_accesses_allavailable() {
524         global $DB, $CFG;
526         $this->resetAfterTest();
528         // Front page, including a forum.
529         $frontpage = $DB->get_record('course', array('id' => SITEID));
530         $forumfront = $this->getDataGenerator()->create_module('forum', array('course' => $frontpage->id));
531         $forumfrontctx = context_module::instance($forumfront->cmid);
533         // Course 1 does not allow guest access.
534         $course1 = $this->getDataGenerator()->create_course((object)array(
535                 'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
536                 'enrol_guest_password_0' => ''));
537         $forum1 = $this->getDataGenerator()->create_module('forum', array('course' => $course1->id));
538         $forum1ctx = context_module::instance($forum1->cmid);
540         // Course 2 does not allow guest but is accessible by all users.
541         $course2 = $this->getDataGenerator()->create_course((object)array(
542                 'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
543                 'enrol_guest_password_0' => ''));
544         $course2ctx = context_course::instance($course2->id);
545         $forum2 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
546         $forum2ctx = context_module::instance($forum2->cmid);
547         assign_capability('moodle/course:view', CAP_ALLOW, $CFG->defaultuserroleid, $course2ctx->id);
549         // Course 3 allows guest access without password.
550         $course3 = $this->getDataGenerator()->create_course((object)array(
551                 'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
552                 'enrol_guest_password_0' => ''));
553         $forum3 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id));
554         $forum3ctx = context_module::instance($forum3->cmid);
556         // Student user is enrolled in course 1.
557         $student = $this->getDataGenerator()->create_user();
558         $this->getDataGenerator()->enrol_user($student->id, $course1->id, 'student');
560         // No access user is just a user with no permissions.
561         $noaccess = $this->getDataGenerator()->create_user();
563         // First test without the all available option.
564         $search = testable_core_search::instance();
566         // Admin user can access everything.
567         $this->setAdminUser();
568         $this->assertTrue($search->get_areas_user_accesses());
570         // No-access user can access only the front page forum.
571         $this->setUser($noaccess);
572         $contexts = $search->get_areas_user_accesses();
573         $this->assertEquals([$forumfrontctx->id], array_keys($contexts[$this->forumpostareaid]));
575         // Student can access the front page forum plus the enrolled one.
576         $this->setUser($student);
577         $contexts = $search->get_areas_user_accesses();
578         $this->assertEquals([$forum1ctx->id, $forumfrontctx->id],
579                 array_keys($contexts[$this->forumpostareaid]));
581         // Now turn on the all available option.
582         set_config('searchallavailablecourses', 1);
584         // Admin user can access everything.
585         $this->setAdminUser();
586         $this->assertTrue($search->get_areas_user_accesses());
588         // No-access user can access the front page forum and course 2, 3.
589         $this->setUser($noaccess);
590         $contexts = $search->get_areas_user_accesses();
591         $this->assertEquals([$forum2ctx->id, $forum3ctx->id, $forumfrontctx->id],
592                 array_keys($contexts[$this->forumpostareaid]));
594         // Student can access the front page forum plus the enrolled one plus courses 2, 3.
595         $this->setUser($student);
596         $contexts = $search->get_areas_user_accesses();
597         $this->assertEquals([$forum1ctx->id, $forum2ctx->id, $forum3ctx->id, $forumfrontctx->id],
598                 array_keys($contexts[$this->forumpostareaid]));
599     }
601     /**
602      * test_is_search_area
603      *
604      * @return void
605      */
606     public function test_is_search_area() {
608         $this->assertFalse(testable_core_search::is_search_area('\asd\asd'));
609         $this->assertFalse(testable_core_search::is_search_area('\mod_forum\search\posta'));
610         $this->assertFalse(testable_core_search::is_search_area('\core_search\base_mod'));
611         $this->assertTrue(testable_core_search::is_search_area('\mod_forum\search\post'));
612         $this->assertTrue(testable_core_search::is_search_area('\\mod_forum\\search\\post'));
613         $this->assertTrue(testable_core_search::is_search_area('mod_forum\\search\\post'));
614     }