MDL-41219 course: Make properties of course_modinfo read-only
[moodle.git] / lib / tests / modinfolib_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  * Unit tests for lib/modinfolib.php.
19  *
20  * @package    core
21  * @category   phpunit
22  * @copyright  2012 Andrew Davis
23  */
25 defined('MOODLE_INTERNAL') || die();
27 global $CFG;
28 require_once($CFG->libdir . '/modinfolib.php');
29 require_once($CFG->libdir . '/conditionlib.php');
31 /**
32  * Unit tests for modinfolib.php
33  *
34  * @copyright 2012 Andrew Davis
35  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class core_modinfolib_testcase extends advanced_testcase {
38     public function test_section_info_properties() {
39         global $DB, $CFG;
41         $this->resetAfterTest();
42         $oldcfgenableavailability = $CFG->enableavailability;
43         $oldcfgenablecompletion = $CFG->enablecompletion;
44         set_config('enableavailability', 1);
45         set_config('enablecompletion', 1);
46         $this->setAdminUser();
48         // Generate the course and pre-requisite module.
49         $course = $this->getDataGenerator()->create_course(
50                 array('format' => 'topics',
51                     'numsections' => 3,
52                     'enablecompletion' => 1,
53                     'groupmode' => SEPARATEGROUPS,
54                     'forcegroupmode' => 0),
55                 array('createsections' => true));
56         $coursecontext = context_course::instance($course->id);
57         $prereqforum = $this->getDataGenerator()->create_module('forum',
58                 array('course' => $course->id),
59                 array('completion' => 1));
61         // Generate the module and add availability conditions.
62         $conditionscompletion = array($prereqforum->cmid => COMPLETION_COMPLETE);
63         $conditionsgrade = array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing'));
64         $conditionsfield = array('email' => (object)array(
65             'fieldname' => 'email',
66             'operator' => 'contains',
67             'value' => 'test'
68         ));
69         $sectiondb = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2));
70         $ci = new condition_info_section((object)array('id' => $sectiondb->id), CONDITION_MISSING_EVERYTHING);
71         foreach ($conditionscompletion as $cmid => $requiredcompletion) {
72             $ci->add_completion_condition($cmid, $requiredcompletion);
73         }
74         foreach ($conditionsgrade as $gradeid => $conditiongrade) {
75             $ci->add_grade_condition($gradeid, $conditiongrade->min, $conditiongrade->max, true);
76         }
77         foreach ($conditionsfield as $conditionfield) {
78             $ci->add_user_field_condition($conditionfield->fieldname, $conditionfield->operator, $conditionfield->value);
79         }
81         // Create and enrol a student.
82         $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
83         $student = $this->getDataGenerator()->create_user();
84         role_assign($studentrole->id, $student->id, $coursecontext);
85         $enrolplugin = enrol_get_plugin('manual');
86         $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
87         $enrolplugin->enrol_user($enrolinstance, $student->id);
88         $this->setUser($student);
90         // Get modinfo.
91         $modinfo = get_fast_modinfo($course->id);
92         $si = $modinfo->get_section_info(2);
94         $this->assertEquals($sectiondb->id, $si->id);
95         $this->assertEquals($sectiondb->course, $si->course);
96         $this->assertEquals($sectiondb->section, $si->section);
97         $this->assertEquals($sectiondb->name, $si->name);
98         $this->assertEquals($sectiondb->visible, $si->visible);
99         $this->assertEquals($sectiondb->summary, $si->summary);
100         $this->assertEquals($sectiondb->summaryformat, $si->summaryformat);
101         $this->assertEquals($sectiondb->showavailability, $si->showavailability);
102         $this->assertEquals($sectiondb->availablefrom, $si->availablefrom);
103         $this->assertEquals($sectiondb->availableuntil, $si->availableuntil);
104         $this->assertEquals($sectiondb->groupingid, $si->groupingid);
105         $this->assertEquals($sectiondb->sequence, $si->sequence); // Since this section does not contain invalid modules.
106         $this->assertEquals($conditionscompletion, $si->conditionscompletion);
107         $this->assertEquals($conditionsgrade, $si->conditionsgrade);
108         $this->assertEquals($conditionsfield, $si->conditionsfield);
110         // Dynamic fields, just test that they can be retrieved (must be carefully tested in each activity type).
111         $this->assertEquals(0, $si->available);
112         $this->assertNotEmpty($si->availableinfo); // Lists all unmet availability conditions.
113         $this->assertEquals(0, $si->uservisible);
115         // Restore settings.
116         set_config('enableavailability', $oldcfgenableavailability);
117         set_config('enablecompletion', $oldcfgenablecompletion);
118     }
120     public function test_cm_info_properties() {
121         global $DB, $CFG;
123         $this->resetAfterTest();
124         $oldcfgenableavailability = $CFG->enableavailability;
125         $oldcfgenablecompletion = $CFG->enablecompletion;
126         set_config('enableavailability', 1);
127         set_config('enablecompletion', 1);
128         $this->setAdminUser();
130         // Generate the course and pre-requisite module.
131         $course = $this->getDataGenerator()->create_course(
132                 array('format' => 'topics',
133                     'numsections' => 3,
134                     'enablecompletion' => 1,
135                     'groupmode' => SEPARATEGROUPS,
136                     'forcegroupmode' => 0),
137                 array('createsections' => true));
138         $coursecontext = context_course::instance($course->id);
139         $prereqforum = $this->getDataGenerator()->create_module('forum',
140                 array('course' => $course->id),
141                 array('completion' => 1));
143         // Generate the module and add availability conditions.
144         $conditionscompletion = array($prereqforum->cmid => COMPLETION_COMPLETE);
145         $conditionsgrade = array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing'));
146         $conditionsfield = array('email' => (object)array(
147             'fieldname' => 'email',
148             'operator' => 'contains',
149             'value' => 'test'
150         ));
151         $assign = $this->getDataGenerator()->create_module('assign',
152                 array('course' => $course->id),
153                 array('idnumber' => 123,
154                     'groupmode' => VISIBLEGROUPS,
155                     'availablefrom' => time() + 3600,
156                     'availableuntil' => time() + 5*3600));
157         $ci = new condition_info((object)array('id' => $assign->cmid), CONDITION_MISSING_EVERYTHING);
158         foreach ($conditionscompletion as $cmid => $requiredcompletion) {
159             $ci->add_completion_condition($cmid, $requiredcompletion);
160         }
161         foreach ($conditionsgrade as $gradeid => $conditiongrade) {
162             $ci->add_grade_condition($gradeid, $conditiongrade->min, $conditiongrade->max, true);
163         }
164         foreach ($conditionsfield as $conditionfield) {
165             $ci->add_user_field_condition($conditionfield->fieldname, $conditionfield->operator, $conditionfield->value);
166         }
168         // Retrieve all related records from DB.
169         $assigndb = $DB->get_record('assign', array('id' => $assign->id));
170         $moduletypedb = $DB->get_record('modules', array('name' => 'assign'));
171         $moduledb = $DB->get_record('course_modules', array('module' => $moduletypedb->id, 'instance' => $assign->id));
172         $sectiondb = $DB->get_record('course_sections', array('id' => $moduledb->section));
173         $modnamessingular = get_module_types_names(false);
174         $modnamesplural = get_module_types_names(true);
176         // Create and enrol a student.
177         $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
178         $student = $this->getDataGenerator()->create_user();
179         role_assign($studentrole->id, $student->id, $coursecontext);
180         $enrolplugin = enrol_get_plugin('manual');
181         $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
182         $enrolplugin->enrol_user($enrolinstance, $student->id);
183         $this->setUser($student);
185         // Emulate data used in building course cache to receive the same instance of cached_cm_info as was used in building modinfo.
186         $rawmods = get_course_mods($course->id);
187         $cachedcminfo = assign_get_coursemodule_info($rawmods[$moduledb->id]);
189         // Get modinfo.
190         $modinfo = get_fast_modinfo($course->id);
191         $cm = $modinfo->instances['assign'][$assign->id];
193         $this->assertEquals($moduledb->id, $cm->id);
194         $this->assertEquals($assigndb->id, $cm->instance);
195         $this->assertEquals($moduledb->course, $cm->course);
196         $this->assertEquals($moduledb->idnumber, $cm->idnumber);
197         $this->assertEquals($moduledb->added, $cm->added);
198         $this->assertEquals($moduledb->visible, $cm->visible);
199         $this->assertEquals($moduledb->visibleold, $cm->visibleold);
200         $this->assertEquals($moduledb->groupmode, $cm->groupmode);
201         $this->assertEquals(VISIBLEGROUPS, $cm->groupmode);
202         $this->assertEquals($moduledb->groupingid, $cm->groupingid);
203         $this->assertEquals($moduledb->groupmembersonly, $cm->groupmembersonly);
204         $this->assertEquals($course->groupmodeforce, $cm->coursegroupmodeforce);
205         $this->assertEquals($course->groupmode, $cm->coursegroupmode);
206         $this->assertEquals(SEPARATEGROUPS, $cm->coursegroupmode);
207         $this->assertEquals($course->groupmodeforce ? $course->groupmode : $moduledb->groupmode,
208                 $cm->effectivegroupmode); // (since mod_assign supports groups).
209         $this->assertEquals(VISIBLEGROUPS, $cm->effectivegroupmode);
210         $this->assertEquals($moduledb->indent, $cm->indent);
211         $this->assertEquals($moduledb->completion, $cm->completion);
212         $this->assertEquals($moduledb->completiongradeitemnumber, $cm->completiongradeitemnumber);
213         $this->assertEquals($moduledb->completionview, $cm->completionview);
214         $this->assertEquals($moduledb->completionexpected, $cm->completionexpected);
215         $this->assertEquals($moduledb->availablefrom, $cm->availablefrom);
216         $this->assertEquals($moduledb->availableuntil, $cm->availableuntil);
217         $this->assertEquals($moduledb->showavailability, $cm->showavailability);
218         $this->assertEquals($moduledb->showdescription, $cm->showdescription);
219         $this->assertEquals(null, $cm->extra); // Deprecated field. Used in module types that don't return cached_cm_info.
220         $this->assertEquals($cachedcminfo->icon, $cm->icon);
221         $this->assertEquals($cachedcminfo->iconcomponent, $cm->iconcomponent);
222         $this->assertEquals('assign', $cm->modname);
223         $this->assertEquals($moduledb->module, $cm->module);
224         $this->assertEquals($cachedcminfo->name, $cm->name);
225         $this->assertEquals($sectiondb->section, $cm->sectionnum);
226         $this->assertEquals($moduledb->section, $cm->section);
227         $this->assertEquals($conditionscompletion, $cm->conditionscompletion);
228         $this->assertEquals($conditionsgrade, $cm->conditionsgrade);
229         $this->assertEquals($conditionsfield, $cm->conditionsfield);
230         $this->assertEquals(context_module::instance($moduledb->id), $cm->context);
231         $this->assertEquals($modnamessingular['assign'], $cm->modfullname);
232         $this->assertEquals($modnamesplural['assign'], $cm->modplural);
233         $this->assertEquals(new moodle_url('/mod/assign/view.php', array('id' => $moduledb->id)), $cm->url);
234         $this->assertEquals($cachedcminfo->customdata, $cm->customdata);
236         // Dynamic fields, just test that they can be retrieved (must be carefully tested in each activity type).
237         $this->assertNotEmpty($cm->availableinfo); // Lists all unmet availability conditions.
238         $this->assertEquals(0, $cm->uservisible);
239         $this->assertEquals('', $cm->extraclasses);
240         $this->assertEquals('', $cm->onclick);
241         $this->assertEquals(null, $cm->afterlink);
242         $this->assertEquals(null, $cm->afterediticons);
243         $this->assertEquals('', $cm->content);
245         // Attempt to access and set non-existing field.
246         $this->assertTrue(empty($modinfo->somefield));
247         $this->assertFalse(isset($modinfo->somefield));
248         $cm->somefield;
249         $this->assertDebuggingCalled();
250         $cm->somefield = 'Some value';
251         $this->assertDebuggingCalled();
252         $this->assertEmpty($cm->somefield);
253         $this->assertDebuggingCalled();
255         // Attempt to overwrite an existing field.
256         $prevvalue = $cm->name;
257         $this->assertNotEmpty($cm->name);
258         $this->assertFalse(empty($cm->name));
259         $this->assertTrue(isset($cm->name));
260         $cm->name = 'Illegal overwriting';
261         $this->assertDebuggingCalled();
262         $this->assertEquals($prevvalue, $cm->name);
263         $this->assertDebuggingNotCalled();
265         // Restore settings.
266         set_config('enableavailability', $oldcfgenableavailability);
267         set_config('enablecompletion', $oldcfgenablecompletion);
268     }
270     public function test_course_modinfo_properties() {
271         global $USER, $DB;
273         $this->resetAfterTest();
274         $this->setAdminUser();
276         // Generate the course and some modules. Make one section hidden.
277         $course = $this->getDataGenerator()->create_course(
278                 array('format' => 'topics',
279                     'numsections' => 3),
280                 array('createsections' => true));
281         $DB->execute('UPDATE {course_sections} SET visible = 0 WHERE course = ? and section = ?',
282                 array($course->id, 3));
283         $coursecontext = context_course::instance($course->id);
284         $forum0 = $this->getDataGenerator()->create_module('forum',
285                 array('course' => $course->id), array('section' => 0));
286         $assign0 = $this->getDataGenerator()->create_module('assign',
287                 array('course' => $course->id), array('section' => 0, 'visible' => 0));
288         $forum1 = $this->getDataGenerator()->create_module('forum',
289                 array('course' => $course->id), array('section' => 1));
290         $assign1 = $this->getDataGenerator()->create_module('assign',
291                 array('course' => $course->id), array('section' => 1));
292         $page1 = $this->getDataGenerator()->create_module('page',
293                 array('course' => $course->id), array('section' => 1));
294         $page3 = $this->getDataGenerator()->create_module('page',
295                 array('course' => $course->id), array('section' => 3));
297         $modinfo = get_fast_modinfo($course->id);
299         $this->assertEquals(array($forum0->cmid, $assign0->cmid, $forum1->cmid, $assign1->cmid, $page1->cmid, $page3->cmid),
300                 array_keys($modinfo->cms));
301         $this->assertEquals($course->id, $modinfo->courseid);
302         $this->assertEquals($USER->id, $modinfo->userid);
303         $this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid),
304             1 => array($forum1->cmid, $assign1->cmid, $page1->cmid), 3 => array($page3->cmid)), $modinfo->sections);
305         $this->assertEquals(array('forum', 'assign', 'page'), array_keys($modinfo->instances));
306         $this->assertEquals(array($assign0->id, $assign1->id), array_keys($modinfo->instances['assign']));
307         $this->assertEquals(array($forum0->id, $forum1->id), array_keys($modinfo->instances['forum']));
308         $this->assertEquals(array($page1->id, $page3->id), array_keys($modinfo->instances['page']));
309         $this->assertEquals(groups_get_user_groups($course->id), $modinfo->groups);
310         $this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid),
311             1 => array($forum1->cmid, $assign1->cmid, $page1->cmid),
312             3 => array($page3->cmid)), $modinfo->get_sections());
313         $this->assertEquals(array(0, 1, 2, 3), array_keys($modinfo->get_section_info_all()));
314         $this->assertEquals($forum0->cmid . ',' . $assign0->cmid, $modinfo->get_section_info(0)->sequence);
315         $this->assertEquals($forum1->cmid . ',' . $assign1->cmid . ',' . $page1->cmid, $modinfo->get_section_info(1)->sequence);
316         $this->assertEquals('', $modinfo->get_section_info(2)->sequence);
317         $this->assertEquals($page3->cmid, $modinfo->get_section_info(3)->sequence);
318         $this->assertEquals($course->id, $modinfo->get_course()->id);
319         $this->assertEquals(array('assign', 'forum', 'page'),
320                 array_keys($modinfo->get_used_module_names()));
321         $this->assertEquals(array('assign', 'forum', 'page'),
322                 array_keys($modinfo->get_used_module_names(true)));
323         // Admin can see hidden modules/sections.
324         $this->assertTrue($modinfo->cms[$assign0->cmid]->uservisible);
325         $this->assertTrue($modinfo->get_section_info(3)->uservisible);
327         // Get modinfo for non-current user (without capability to view hidden activities/sections).
328         $user = $this->getDataGenerator()->create_user();
329         $modinfo = get_fast_modinfo($course->id, $user->id);
330         $this->assertEquals($user->id, $modinfo->userid);
331         $this->assertFalse($modinfo->cms[$assign0->cmid]->uservisible);
332         $this->assertFalse($modinfo->get_section_info(3)->uservisible);
334         // Attempt to access and set non-existing field.
335         $this->assertTrue(empty($modinfo->somefield));
336         $this->assertFalse(isset($modinfo->somefield));
337         $modinfo->somefield;
338         $this->assertDebuggingCalled();
339         $modinfo->somefield = 'Some value';
340         $this->assertDebuggingCalled();
341         $this->assertEmpty($modinfo->somefield);
342         $this->assertDebuggingCalled();
344         // Attempt to overwrite existing field.
345         $this->assertFalse(empty($modinfo->cms));
346         $this->assertTrue(isset($modinfo->cms));
347         $modinfo->cms = 'Illegal overwriting';
348         $this->assertDebuggingCalled();
349         $this->assertNotEquals('Illegal overwriting', $modinfo->cms);
350     }
352     /**
353      * Test is_user_access_restricted_by_group()
354      *
355      * The underlying groups system is more thoroughly tested in lib/tests/grouplib_test.php
356      */
357     public function test_is_user_access_restricted_by_group() {
358         global $DB, $CFG, $USER;
360         $this->resetAfterTest();
362         // Create a course.
363         $course = $this->getDataGenerator()->create_course();
364         $coursecontext = context_course::instance($course->id);
366         // Create a mod_assign instance.
367         $assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id));
368         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign->id];
370         // Create and enrol a student.
371         // Enrolment is necessary for groups to work.
372         $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
373         $student = $this->getDataGenerator()->create_user();
374         role_assign($studentrole->id, $student->id, $coursecontext);
375         $enrolplugin = enrol_get_plugin('manual');
376         $enrolplugin->add_instance($course);
377         $enrolinstances = enrol_get_instances($course->id, false);
378         foreach ($enrolinstances as $enrolinstance) {
379             if ($enrolinstance->enrol === 'manual') {
380                 break;
381             }
382         }
383         $enrolplugin->enrol_user($enrolinstance, $student->id);
385         // Switch to a student and reload the context info.
386         $this->setUser($student);
387         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign->id];
389         // Create up a teacher.
390         $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
391         $teacher = $this->getDataGenerator()->create_user();
392         role_assign($teacherrole->id, $teacher->id, $coursecontext);
394         // Create 2 groupings.
395         $grouping1 = $this->getDataGenerator()->create_grouping(array('courseid' => $course->id, 'name' => 'grouping1'));
396         $grouping2 = $this->getDataGenerator()->create_grouping(array('courseid' => $course->id, 'name' => 'grouping2'));
398         // Create 2 groups and put them in the groupings.
399         $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'idnumber' => 'group1'));
400         groups_assign_grouping($grouping1->id, $group1->id);
401         $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'idnumber' => 'group2'));
402         groups_assign_grouping($grouping2->id, $group2->id);
404         // If groups are disabled, the activity isn't restricted.
405         $CFG->enablegroupmembersonly = false;
406         $this->assertFalse($cm_info->is_user_access_restricted_by_group());
408         // Turn groups setting on.
409         $CFG->enablegroupmembersonly = true;
410         // Create a mod_assign instance with "group members only", the activity should not be restricted.
411         $assignnogroups = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id),
412             array('groupmembersonly' => NOGROUPS));
413         $cm_info = get_fast_modinfo($course->id)->instances['assign'][$assignnogroups->id];
414         $this->assertFalse($cm_info->is_user_access_restricted_by_group());
416         // If "group members only" is on but user is in the wrong group, the activity is restricted.
417         $assignsepgroups = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id),
418             array('groupmembersonly' => SEPARATEGROUPS, 'groupingid' => $grouping1->id));
419         $this->assertTrue(groups_add_member($group2, $USER));
420         get_fast_modinfo($course->id, 0, true);
421         $cm_info = get_fast_modinfo($course->id)->instances['assign'][$assignsepgroups->id];
422         $this->assertEquals($grouping1->id, $cm_info->groupingid);
423         $this->assertTrue($cm_info->is_user_access_restricted_by_group());
425         // If the user is in the required group, the activity isn't restricted.
426         groups_remove_member($group2, $USER);
427         $this->assertTrue(groups_add_member($group1, $USER));
428         get_fast_modinfo($course->id, 0, true);
429         $cm_info = get_fast_modinfo($course->id)->instances['assign'][$assignsepgroups->id];
430         $this->assertFalse($cm_info->is_user_access_restricted_by_group());
432         // Switch to a teacher and reload the context info.
433         $this->setUser($teacher);
434         $cm_info = get_fast_modinfo($course->id)->instances['assign'][$assignsepgroups->id];
436         // If the user isn't in the required group but has 'moodle/site:accessallgroups', the activity isn't restricted.
437         $this->assertTrue(has_capability('moodle/site:accessallgroups', $coursecontext));
438         $this->assertFalse($cm_info->is_user_access_restricted_by_group());
439     }
441     /**
442      * Test is_user_access_restricted_by_conditional_access()
443      *
444      * The underlying conditional access system is more thoroughly tested in lib/tests/conditionlib_test.php
445      */
446     public function test_is_user_access_restricted_by_conditional_access() {
447         global $DB, $CFG;
449         $this->resetAfterTest();
451         // Create a course.
452         $course = $this->getDataGenerator()->create_course();
453         // 1. Create an activity that is currently unavailable and hidden entirely (for students).
454         $assign1 = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id),
455                 array('availablefrom' => time() + 10000, 'showavailability' => CONDITION_STUDENTVIEW_HIDE));
456         // 2. Create an activity that is currently available.
457         $assign2 = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id));
458         // 3. Create an activity that is currently unavailable and set to be greyed out.
459         $assign3 = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id),
460                 array('availablefrom' => time() + 10000, 'showavailability' => CONDITION_STUDENTVIEW_SHOW));
462         // Set up a teacher.
463         $coursecontext = context_course::instance($course->id);
464         $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
465         $teacher = $this->getDataGenerator()->create_user();
466         role_assign($teacherrole->id, $teacher->id, $coursecontext);
468         // If conditional availability is disabled the activity will always be unrestricted.
469         $CFG->enableavailability = false;
470         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign1->id];
471         $this->assertFalse($cm_info->is_user_access_restricted_by_conditional_access());
473         // Turn on conditional availability and reset the get_fast_modinfo cache.
474         $CFG->enableavailability = true;
475         get_fast_modinfo($course, 0, true);
477         // The unavailable, hidden entirely activity should now be restricted.
478         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign1->id];
479         $this->assertFalse($cm_info->available);
480         $this->assertEquals(CONDITION_STUDENTVIEW_HIDE, $cm_info->showavailability);
481         $this->assertTrue($cm_info->is_user_access_restricted_by_conditional_access());
483         // If the activity is available it should not be restricted.
484         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign2->id];
485         $this->assertTrue($cm_info->available);
486         $this->assertFalse($cm_info->is_user_access_restricted_by_conditional_access());
488         // If the activity is unavailable and set to be greyed out it should not be restricted.
489         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign3->id];
490         $this->assertFalse($cm_info->available);
491         $this->assertEquals(CONDITION_STUDENTVIEW_SHOW, $cm_info->showavailability);
492         $this->assertFalse($cm_info->is_user_access_restricted_by_conditional_access());
494         // If the activity is unavailable and set to be hidden entirely its restricted unless user has 'moodle/course:viewhiddenactivities'.
495         // Switch to a teacher and reload the context info.
496         $this->setUser($teacher);
497         $cm_info = get_fast_modinfo($course)->instances['assign'][$assign1->id];
498         $this->assertFalse($cm_info->available);
499         $this->assertEquals(CONDITION_STUDENTVIEW_HIDE, $cm_info->showavailability);
501         $this->assertTrue(has_capability('moodle/course:viewhiddenactivities', $coursecontext));
502         $this->assertFalse($cm_info->is_user_access_restricted_by_conditional_access());
503     }
505     public function test_is_user_access_restricted_by_capability() {
506         global $DB;
508         $this->resetAfterTest();
510         // Create a course and a mod_assign instance.
511         $course = $this->getDataGenerator()->create_course();
512         $assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id));
514         // Create and enrol a student.
515         $coursecontext = context_course::instance($course->id);
516         $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
517         $student = $this->getDataGenerator()->create_user();
518         role_assign($studentrole->id, $student->id, $coursecontext);
519         $enrolplugin = enrol_get_plugin('manual');
520         $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
521         $enrolplugin->enrol_user($enrolinstance, $student->id);
522         $this->setUser($student);
524         // Make sure student can see the module.
525         $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id];
526         $this->assertTrue($cm->uservisible);
527         $this->assertFalse($cm->is_user_access_restricted_by_capability());
529         // Prohibit student to view mod_assign for the course.
530         role_change_permission($studentrole->id, $coursecontext, 'mod/assign:view', CAP_PROHIBIT);
531         get_fast_modinfo($course->id, 0, true);
532         $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id];
533         $this->assertFalse($cm->uservisible);
534         $this->assertTrue($cm->is_user_access_restricted_by_capability());
536         // Restore permission to student to view mod_assign for the course.
537         role_change_permission($studentrole->id, $coursecontext, 'mod/assign:view', CAP_INHERIT);
538         get_fast_modinfo($course->id, 0, true);
539         $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id];
540         $this->assertTrue($cm->uservisible);
541         $this->assertFalse($cm->is_user_access_restricted_by_capability());
543         // Prohibit student to view mod_assign for the particular module.
544         role_change_permission($studentrole->id, context_module::instance($cm->id), 'mod/assign:view', CAP_PROHIBIT);
545         get_fast_modinfo($course->id, 0, true);
546         $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id];
547         $this->assertFalse($cm->uservisible);
548         $this->assertTrue($cm->is_user_access_restricted_by_capability());
550         // Check calling get_fast_modinfo() for different user:
551         $this->setAdminUser();
552         $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id];
553         $this->assertTrue($cm->uservisible);
554         $this->assertFalse($cm->is_user_access_restricted_by_capability());
555         $cm = get_fast_modinfo($course->id, $student->id)->instances['assign'][$assign->id];
556         $this->assertFalse($cm->uservisible);
557         $this->assertTrue($cm->is_user_access_restricted_by_capability());
558     }