b4e7cee0dcad41fef1fff4048210b402ce99427c
[moodle.git] / lib / tests / conditionlib_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  * Tests for conditional activities
19  *
20  * @package    core
21  * @category   phpunit
22  * @copyright  &copy; 2008 The Open University
23  * @author     Sam Marshall
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU Public License
25  */
27 defined('MOODLE_INTERNAL') || die();
29 global $CFG;
30 require_once($CFG->dirroot . '/lib/conditionlib.php');
33 class conditionlib_testcase extends advanced_testcase {
34     private $oldcfg, $olduser;
36     protected function setUp() {
37         global $CFG, $USER, $DB;
38         parent::setUp();
40         $this->resetAfterTest(true);
42         $CFG->enableavailability = 1;
43         $CFG->enablecompletion = 1;
44         $user = $this->getDataGenerator()->create_user();;
45         $this->setUser($user);
47         // Reset modinfo cache before each request
48         $reset = 'reset';
49         get_fast_modinfo($reset);
50     }
52     function test_constructor() {
53         global $DB,$CFG;
54         $cm=new stdClass;
56         // Test records
57         $id=$DB->insert_record('course_modules',(object)array(
58             'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,'course'=>64));
60         // no ID
61         try {
62             $test=new condition_info($cm);
63             $this->fail();
64         } catch(coding_exception $e) {
65         }
67         // no other data
68         $cm->id=$id;
69         $test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
70         $this->assertEquals(
71             (object)array('id'=>$id,'showavailability'=>1,
72                 'availablefrom'=>17,'availableuntil'=>398,'course'=>64,
73                 'conditionsgrade'=>array(), 'conditionscompletion'=>array(),
74                 'visible' => 1, 'conditionsfield' => array()),
75             $test->get_full_course_module());
77         // just the course_modules stuff; check it doesn't request that from db
78         $cm->showavailability=0;
79         $cm->availablefrom=2;
80         $cm->availableuntil=74;
81         $cm->course=38;
82         $cm->visible = 1;
83         $test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE);
84         $this->assertEquals(
85             (object)array('id'=>$id,'showavailability'=>0,
86                 'availablefrom'=>2,'availableuntil'=>74,'course'=>38,
87                 'conditionsgrade' => array(), 'conditionscompletion' => array(),
88                 'visible' => 1, 'conditionsfield' => array()),
89             $test->get_full_course_module());
91         // Now let's add some actual grade/completion conditions
92         $DB->insert_record('course_modules_availability',(object)array(
93             'coursemoduleid'=>$id,
94             'sourcecmid'=>42,
95             'requiredcompletion'=>2
96         ));
97         $DB->insert_record('course_modules_availability',(object)array(
98             'coursemoduleid'=>$id,
99             'sourcecmid'=>666,
100             'requiredcompletion'=>1
101         ));
102         $DB->insert_record('course_modules_availability',(object)array(
103             'coursemoduleid'=>$id,
104             'gradeitemid'=>37,
105             'grademin'=>5.5
106         ));
108         $cm=(object)array('id'=>$id);
109         $test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
110         $fullcm=$test->get_full_course_module();
111         $this->assertEquals(array(42=>2,666=>1),$fullcm->conditionscompletion);
112         $this->assertEquals(array(37=>(object)array('min'=>5.5,'max'=>null,'name'=>'!missing')),
113             $fullcm->conditionsgrade);
114     }
116     /**
117      * Same as above test but for course_sections instead of course_modules.
118      */
119     public function test_section_constructor() {
120         global $DB, $CFG;
122         // Test records
123         $id = $DB->insert_record('course_sections', (object)array(
124                 'showavailability' => 1, 'availablefrom' => 17,
125                 'availableuntil' => 398, 'course' => 64, 'groupingid' => 13));
127         // No ID
128         $section = new stdClass;
129         try {
130             $test = new condition_info_section($section);
131             $this->fail();
132         } catch (coding_exception $e) {
133             // Do nothing
134         }
136         // No other data
137         $section->id = $id;
138         $test = new condition_info_section($section, CONDITION_MISSING_EVERYTHING);
139         $this->assertEquals(
140                 (object)array('id' => $id, 'showavailability' => 1, 'groupingid' => 13,
141                     'availablefrom' => 17, 'availableuntil' => 398, 'course' => 64,
142                     'conditionsgrade' => array(), 'conditionscompletion' => array(),
143                     'visible' => 1, 'conditionsfield' => array()),
144                 $test->get_full_section());
146         // Just the course_sections stuff; check it doesn't request that from db
147         // (by using fake values and ensuring it still has those)
148         $section->showavailability = 0;
149         $section->availablefrom = 2;
150         $section->availableuntil = 74;
151         $section->course = 38;
152         $section->groupingid = 99;
153         $section->visible = 1;
154         $test = new condition_info_section($section, CONDITION_MISSING_EXTRATABLE);
155         $this->assertEquals(
156                 (object)array('id' => $id, 'showavailability' => 0, 'groupingid' => 99,
157                     'availablefrom' => 2, 'availableuntil' => 74, 'course' => 38,
158                     'conditionsgrade' => array(), 'conditionscompletion' => array(),
159                     'visible' => 1, 'conditionsfield' => array()),
160                 $test->get_full_section());
162         // Now let's add some actual grade/completion conditions
163         $DB->insert_record('course_sections_availability', (object)array(
164                 'coursesectionid' => $id,
165                 'sourcecmid' => 42,
166                 'requiredcompletion' => 2
167         ));
168         $DB->insert_record('course_sections_availability', (object)array(
169                 'coursesectionid' => $id,
170                 'sourcecmid' => 666,
171                 'requiredcompletion' => 1
172         ));
173         $DB->insert_record('course_sections_availability', (object)array(
174                 'coursesectionid' => $id,
175                 'gradeitemid' => 37,
176                 'grademin' => 5.5
177         ));
179         $section = (object)array('id' => $id);
180         $test = new condition_info_section($section, CONDITION_MISSING_EVERYTHING);
181         $fullsection = $test->get_full_section();
182         $this->assertEquals(array(42 => 2, 666 => 1), $fullsection->conditionscompletion);
183         $this->assertEquals(array(37 => (object)array('min' => 5.5, 'max' => null, 'name' => '!missing')),
184                 $fullsection->conditionsgrade);
185     }
187     private function make_course() {
188         global $DB;
189         $categoryid = $DB->insert_record('course_categories', (object)array('name'=>'conditionlibtest'));
190         $courseid = $DB->insert_record('course', (object)array(
191             'fullname'=>'Condition test','shortname'=>'CT1',
192             'category'=>$categoryid,'enablecompletion'=>1));
193         context_course::instance($courseid);
194         return $courseid;
195     }
197     private function make_course_module($courseid,$params=array()) {
198         global $DB;
199         static $moduleid=0;
200         if(!$moduleid) {
201             $moduleid=$DB->get_field('modules','id',array('name'=>'resource'));
202         }
204         $rid=$DB->insert_record('resource',(object)array('course'=>$courseid,
205             'name'=>'xxx','alltext'=>'','popup'=>''));
206         $settings=(object)array(
207             'course'=>$courseid,'module'=>$moduleid,'instance'=>$rid);
208         foreach($params as $name=>$value) {
209             $settings->{$name}=$value;
210         }
211         $cmid = $DB->insert_record('course_modules',$settings);
212         rebuild_course_cache($courseid, true);
213         return $cmid;
214     }
216     private function make_section($courseid, $cmids, $sectionnum=0, $params=array()) {
217         global $DB;
218         $record = (object)array(
219             'course' => $courseid,
220             'sequence' => implode(',', $cmids),
221             'section' => $sectionnum);
222         foreach ($params as $name => $value) {
223             $record->{$name} = $value;
224         }
225         $sectionid = $DB->insert_record('course_sections', $record);
226         rebuild_course_cache($courseid, true);
227         return $sectionid;
228     }
230     private function make_grouping($courseid, $name) {
231         global $CFG;
232         require_once($CFG->dirroot . '/group/lib.php');
233         return groups_create_grouping((object)array('courseid' => $courseid,
234                 'name' => $name));
235     }
237     private function make_group($courseid, $name, $groupingid=0) {
238         global $CFG;
239         require_once($CFG->dirroot . '/group/lib.php');
240         $groupid = groups_create_group((object)array('courseid' => $courseid,
241                 'name' => $name));
242         if ($groupingid) {
243             groups_assign_grouping($groupingid, $groupid);
244         }
245         return $groupid;
246     }
248     function test_modinfo() {
249         global $DB;
251         // Let's make a course
252         $courseid=$this->make_course();
254         // Now let's make a couple modules on that course
255         $cmid1=$this->make_course_module($courseid,array(
256             'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,
257             'completion'=>COMPLETION_TRACKING_MANUAL));
258         $cmid2=$this->make_course_module($courseid,array(
259             'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
260         $this->make_section($courseid,array($cmid1,$cmid2));
262         // Add a fake grade item
263         $gradeitemid=$DB->insert_record('grade_items',(object)array(
264             'courseid'=>$courseid,'itemname'=>'frog'));
266         // One of the modules has grade and completion conditions, other doesn't
267         $DB->insert_record('course_modules_availability',(object)array(
268             'coursemoduleid'=>$cmid2,
269             'sourcecmid'=>$cmid1,
270             'requiredcompletion'=>1
271         ));
272         $DB->insert_record('course_modules_availability',(object)array(
273             'coursemoduleid'=>$cmid2,
274             'gradeitemid'=>$gradeitemid,
275             'grademin'=>5.5
276         ));
278         // Okay sweet, now get modinfo
279         $course = $DB->get_record('course',array('id'=>$courseid));
280         $modinfo=get_fast_modinfo($course);
282         // Test basic data
283         $this->assertEquals(1,$modinfo->cms[$cmid1]->showavailability);
284         $this->assertEquals(17,$modinfo->cms[$cmid1]->availablefrom);
285         $this->assertEquals(398,$modinfo->cms[$cmid1]->availableuntil);
286         $this->assertEquals(0,$modinfo->cms[$cmid2]->showavailability);
287         $this->assertEquals(0,$modinfo->cms[$cmid2]->availablefrom);
288         $this->assertEquals(0,$modinfo->cms[$cmid2]->availableuntil);
290         // Test condition arrays
291         $this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionscompletion);
292         $this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionsgrade);
293         $this->assertEquals(array($cmid1=>1),
294             $modinfo->cms[$cmid2]->conditionscompletion);
295         $this->assertEquals(array($gradeitemid=>(object)array('min'=>5.5,'max'=>null,'name'=>'frog')),
296             $modinfo->cms[$cmid2]->conditionsgrade);
297     }
299     public function test_section_modinfo() {
300         global $DB;
302         // Let's make a course
303         $courseid = $this->make_course();
305         // Now let's make a couple sections on that course, one of which has a cm
306         $cmid = $this->make_course_module($courseid);
307         $sectionid1 = $this->make_section($courseid, array($cmid), 1, array(
308                 'showavailability' => 1, 'availablefrom' => 17,
309                 'availableuntil' => 398, 'groupingid' => 13));
310         $sectionid2 = $this->make_section($courseid, array(), 2);
312         // Add a fake grade item
313         $gradeitemid = $DB->insert_record('grade_items', (object)array(
314                 'courseid' => $courseid, 'itemname' => 'frog'));
316         // One of the sections has grade and completion conditions, other doesn't
317         $DB->insert_record('course_sections_availability', (object)array(
318             'coursesectionid' => $sectionid2,
319             'sourcecmid' => $cmid,
320             'requiredcompletion'=>1
321         ));
322         $DB->insert_record('course_sections_availability', (object)array(
323             'coursesectionid' => $sectionid2,
324             'gradeitemid' => $gradeitemid,
325             'grademin' => 5.5
326         ));
328         rebuild_course_cache($courseid, true);
329         // Okay sweet, now get modinfo
330         $course = $DB->get_record('course', array('id' => $courseid));
331         $modinfo = get_fast_modinfo($course);
333         // Test basic data
334         $section1 = $modinfo->get_section_info(1);
335         $this->assertEquals(1, $section1->showavailability);
336         $this->assertEquals(17, $section1->availablefrom);
337         $this->assertEquals(398, $section1->availableuntil);
338         $this->assertEquals(13, $section1->groupingid);
339         $section2 = $modinfo->get_section_info(2);
340         $this->assertEquals(0, $section2->showavailability);
341         $this->assertEquals(0, $section2->availablefrom);
342         $this->assertEquals(0, $section2->availableuntil);
343         $this->assertEquals(0, $section2->groupingid);
345         // Test condition arrays
346         $this->assertEquals(array(), $section1->conditionscompletion);
347         $this->assertEquals(array(), $section1->conditionsgrade);
348         $this->assertEquals(array($cmid => 1),
349                 $section2->conditionscompletion);
350         $this->assertEquals(array($gradeitemid => (object)array('min' => 5.5, 'max' => null, 'name' => 'frog')),
351                 $section2->conditionsgrade);
352     }
354     function test_add_and_remove() {
355         global $DB;
356         // Make course and module
357         $courseid=$this->make_course();
358         $cmid=$this->make_course_module($courseid,array(
359             'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
360         $this->make_section($courseid,array($cmid));
362         // Check it has no conditions
363         $test1=new condition_info((object)array('id'=>$cmid),
364             CONDITION_MISSING_EVERYTHING);
365         $cm=$test1->get_full_course_module();
366         $this->assertEquals(array(),$cm->conditionscompletion);
367         $this->assertEquals(array(),$cm->conditionsgrade);
369         // Add conditions of each type
370         $test1->add_completion_condition(13,3);
371         $this->assertEquals(array(13=>3),$cm->conditionscompletion);
372         $test1->add_grade_condition(666,0.4,null,true);
373         $this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
374             $cm->conditionsgrade);
376         // Check they were really added in db
377         $test2=new condition_info((object)array('id'=>$cmid),
378             CONDITION_MISSING_EVERYTHING);
379         $cm=$test2->get_full_course_module();
380         $this->assertEquals(array(13=>3),$cm->conditionscompletion);
381         $this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
382             $cm->conditionsgrade);
384         // Wipe conditions
385         $test2->wipe_conditions();
386         $this->assertEquals(array(),$cm->conditionscompletion);
387         $this->assertEquals(array(),$cm->conditionsgrade);
389         // Check they were really wiped
390         $test3=new condition_info((object)array('id'=>$cmid),
391             CONDITION_MISSING_EVERYTHING);
392         $cm=$test3->get_full_course_module();
393         $this->assertEquals(array(),$cm->conditionscompletion);
394         $this->assertEquals(array(),$cm->conditionsgrade);
395     }
397     public function test_section_add_and_remove() {
398         global $DB;
400         // Make course and module
401         $courseid = $this->make_course();
402         $cmid = $this->make_course_module($courseid);
403         $sectionid = $this->make_section($courseid, array($cmid));
405         // Check it has no conditions
406         $test1 = new condition_info_section((object)array('id'=>$sectionid),
407                 CONDITION_MISSING_EVERYTHING);
408         $section = $test1->get_full_section();
409         $this->assertEquals(array(), $section->conditionscompletion);
410         $this->assertEquals(array(), $section->conditionsgrade);
412         // Add conditions of each type
413         $test1->add_completion_condition(13, 3);
414         $this->assertEquals(array(13 => 3), $section->conditionscompletion);
415         $test1->add_grade_condition(666, 0.4, null, true);
416         $this->assertEquals(array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing')),
417                 $section->conditionsgrade);
419         // Check they were really added in db
420         $test2 = new condition_info_section((object)array('id' => $sectionid),
421                 CONDITION_MISSING_EVERYTHING);
422         $section = $test2->get_full_section();
423         $this->assertEquals(array(13 => 3), $section->conditionscompletion);
424         $this->assertEquals(array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing')),
425                 $section->conditionsgrade);
427         // Wipe conditions
428         $test2->wipe_conditions();
429         $this->assertEquals(array(), $section->conditionscompletion);
430         $this->assertEquals(array(), $section->conditionsgrade);
432         // Check they were really wiped
433         $test3 = new condition_info_section((object)array('id' => $cmid),
434                 CONDITION_MISSING_EVERYTHING);
435         $section = $test3->get_full_section();
436         $this->assertEquals(array(), $section->conditionscompletion);
437         $this->assertEquals(array(), $section->conditionsgrade);
438     }
440     function test_is_available() {
441         global $DB,$USER;
442         $courseid=$this->make_course();
444         // No conditions
445         $cmid=$this->make_course_module($courseid);
446         $ci=new condition_info((object)array('id'=>$cmid),
447             CONDITION_MISSING_EVERYTHING);
448         $this->assertTrue($ci->is_available($text,false,0));
449         $this->assertEquals('',$text);
451         // Time (from)
452         $time=time()+100;
453         $cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
454         $ci=new condition_info((object)array('id'=>$cmid),
455             CONDITION_MISSING_EVERYTHING);
456         $this->assertFalse($ci->is_available($text));
457         $this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$text);
459         $time=time()-100;
460         $cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
461         $ci=new condition_info((object)array('id'=>$cmid),
462             CONDITION_MISSING_EVERYTHING);
463         $this->assertTrue($ci->is_available($text));
464         $this->assertEquals('',$text);
465         $this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$ci->get_full_information());
467         // Time (until)
468         $cmid=$this->make_course_module($courseid,array('availableuntil'=>time()-100));
469         $ci=new condition_info((object)array('id'=>$cmid),
470             CONDITION_MISSING_EVERYTHING);
471         $this->assertFalse($ci->is_available($text));
472         $this->assertEquals('',$text);
474         // Completion
475         $oldid=$cmid;
476         $cmid=$this->make_course_module($courseid);
477         $this->make_section($courseid,array($oldid,$cmid));
478         $oldcm=$DB->get_record('course_modules',array('id'=>$oldid));
479         $oldcm->completion=COMPLETION_TRACKING_MANUAL;
480         $DB->update_record('course_modules',$oldcm);
482         // Need to reset modinfo after changing the options
483         rebuild_course_cache($courseid);
485         $ci=new condition_info((object)array('id'=>$cmid),CONDITION_MISSING_EVERYTHING);
486         $ci->add_completion_condition($oldid,COMPLETION_COMPLETE);
487         condition_info::wipe_session_cache();
489         $this->assertFalse($ci->is_available($text,false));
490         $this->assertEquals(get_string('requires_completion_1','condition','xxx'),$text);
491         completion_info::wipe_session_cache();
492         $completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
493         $completion->update_state($oldcm,COMPLETION_COMPLETE);
494         completion_info::wipe_session_cache();
495         condition_info::wipe_session_cache();
497         $this->assertTrue($ci->is_available($text));
498         $this->assertFalse($ci->is_available($text,false,$USER->id+1));
499         completion_info::wipe_session_cache();
500         condition_info::wipe_session_cache();
501         $completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
502         $completion->update_state($oldcm,COMPLETION_INCOMPLETE);
503         $this->assertFalse($ci->is_available($text));
505         $ci->wipe_conditions();
506         $ci->add_completion_condition($oldid,COMPLETION_INCOMPLETE);
507         condition_info::wipe_session_cache();
508         $this->assertTrue($ci->is_available($text));
509         $this->assertTrue($ci->is_available($text,false,$USER->id+1));
511         condition_info::wipe_session_cache();
512         $this->assertTrue($ci->is_available($text,true));
514         // Grade
515         $ci->wipe_conditions();
516         // Add a fake grade item
517         $gradeitemid=$DB->insert_record('grade_items',(object)array(
518             'courseid'=>$courseid,'itemname'=>'frog'));
519         // Add a condition on a value existing...
520         $ci->add_grade_condition($gradeitemid,null,null,true);
521         $this->assertFalse($ci->is_available($text));
522         $this->assertEquals(get_string('requires_grade_any','condition','frog'),$text);
524         // Fake it existing
525         $DB->insert_record('grade_grades',(object)array(
526             'itemid'=>$gradeitemid,'userid'=>$USER->id,'finalgrade'=>3.78));
527         condition_info::wipe_session_cache();
528         $this->assertTrue($ci->is_available($text));
530         condition_info::wipe_session_cache();
531         $this->assertTrue($ci->is_available($text,true));
533         // Now require that user gets more than 3.78001
534         $ci->wipe_conditions();
535         $ci->add_grade_condition($gradeitemid,3.78001,null,true);
536         condition_info::wipe_session_cache();
537         $this->assertFalse($ci->is_available($text));
538         $this->assertEquals(get_string('requires_grade_min','condition','frog'),$text);
540         // ...just on 3.78...
541         $ci->wipe_conditions();
542         $ci->add_grade_condition($gradeitemid,3.78,null,true);
543         condition_info::wipe_session_cache();
544         $this->assertTrue($ci->is_available($text));
546         // ...less than 3.78
547         $ci->wipe_conditions();
548         $ci->add_grade_condition($gradeitemid,null,3.78,true);
549         condition_info::wipe_session_cache();
550         $this->assertFalse($ci->is_available($text));
551         $this->assertEquals(get_string('requires_grade_max','condition','frog'),$text);
553         // ...less than 3.78001
554         $ci->wipe_conditions();
555         $ci->add_grade_condition($gradeitemid,null,3.78001,true);
556         condition_info::wipe_session_cache();
557         $this->assertTrue($ci->is_available($text));
559         // ...in a range that includes it
560         $ci->wipe_conditions();
561         $ci->add_grade_condition($gradeitemid,3,4,true);
562         condition_info::wipe_session_cache();
563         $this->assertTrue($ci->is_available($text));
565         // ...in a range that doesn't include it
566         $ci->wipe_conditions();
567         $ci->add_grade_condition($gradeitemid,4,5,true);
568         condition_info::wipe_session_cache();
569         $this->assertFalse($ci->is_available($text));
570         $this->assertEquals(get_string('requires_grade_range','condition','frog'),$text);
571     }
573     public function test_section_is_available() {
574         global $DB, $USER;
575         $courseid = $this->make_course();
577         // Enrol user (needed for groups)
578         $enrolplugin = enrol_get_plugin('manual');
579         $course = $DB->get_record('course', array('id' => $courseid));
580         $enrolplugin->add_instance($course);
581         $enrolinstances = enrol_get_instances($courseid, false);
582         foreach ($enrolinstances as $enrolinstance) {
583             if ($enrolinstance->enrol === 'manual') {
584                 break;
585             }
586         }
587         $enrolplugin->enrol_user($enrolinstance, $USER->id);
589         // Module for conditions later
590         $cmid = $this->make_course_module($courseid);
592         // No conditions
593         $sectionid = $this->make_section($courseid, array($cmid), 1);
594         $ci = new condition_info_section((object)array('id' => $sectionid),
595                 CONDITION_MISSING_EVERYTHING);
596         $this->assertTrue($ci->is_available($text, false, 0));
597         $this->assertEquals('', $text);
599         // Time (from)
600         $time = time() + 100;
601         $sectionid = $this->make_section($courseid, array(), 2, array('availablefrom' => $time));
602         $ci = new condition_info_section((object)array('id' => $sectionid),
603                 CONDITION_MISSING_EVERYTHING);
604         $this->assertFalse($ci->is_available($text));
605         $timetext = userdate($time, get_string('strftimedate', 'langconfig'));
606         $this->assertRegExp('~' . preg_quote($timetext) . '~', $text);
608         $time=time()-100;
609         $sectionid = $this->make_section($courseid, array(), 3, array('availablefrom' => $time));
610         $ci = new condition_info_section((object)array('id' => $sectionid),
611                 CONDITION_MISSING_EVERYTHING);
612         $this->assertTrue($ci->is_available($text));
613         $this->assertEquals('', $text);
614         $timetext = userdate($time, get_string('strftimedate', 'langconfig'));
615         $this->assertRegExp('~' . preg_quote($timetext) . '~', $ci->get_full_information());
617         // Time (until)
618         $sectionid = $this->make_section($courseid, array(), 4, array('availableuntil' => time() - 100));
619         $ci = new condition_info_section((object)array('id' => $sectionid),
620             CONDITION_MISSING_EVERYTHING);
621         $this->assertFalse($ci->is_available($text));
622         $this->assertEquals('', $text);
624         // Completion: first set up cm
625         $sectionid = $this->make_section($courseid, array(), 5);
626         $cm = $DB->get_record('course_modules', array('id' => $cmid));
627         $cm->completion = COMPLETION_TRACKING_MANUAL;
628         $DB->update_record('course_modules', $cm);
630         // Completion: Reset modinfo after changing the options
631         rebuild_course_cache($courseid);
633         // Completion: Add condition
634         $ci = new condition_info_section((object)array('id' => $sectionid),
635                 CONDITION_MISSING_EVERYTHING);
636         $ci->add_completion_condition($cmid, COMPLETION_COMPLETE);
637         condition_info_section::wipe_session_cache();
639         // Completion: Check
640         $this->assertFalse($ci->is_available($text, false));
641         $this->assertEquals(get_string('requires_completion_1', 'condition', 'xxx'), $text);
642         completion_info::wipe_session_cache();
643         $completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
644         $completion->update_state($cm, COMPLETION_COMPLETE);
645         completion_info::wipe_session_cache();
646         condition_info_section::wipe_session_cache();
647         $this->assertTrue($ci->is_available($text));
648         $this->assertFalse($ci->is_available($text, false, $USER->id + 1));
650         // Completion: Uncheck
651         completion_info::wipe_session_cache();
652         condition_info_section::wipe_session_cache();
653         $completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
654         $completion->update_state($cm, COMPLETION_INCOMPLETE);
655         $this->assertFalse($ci->is_available($text));
657         // Completion: Incomplete condition
658         $ci->wipe_conditions();
659         $ci->add_completion_condition($cmid, COMPLETION_INCOMPLETE);
660         condition_info_section::wipe_session_cache();
661         $this->assertTrue($ci->is_available($text));
662         $this->assertTrue($ci->is_available($text, false, $USER->id + 1));
663         condition_info_section::wipe_session_cache();
664         $this->assertTrue($ci->is_available($text, true));
666         // Grade: Add a fake grade item
667         $gradeitemid = $DB->insert_record('grade_items', (object)array(
668             'courseid' => $courseid, 'itemname' => 'frog'));
670         // Grade: Add a condition on a value existing
671         $ci->wipe_conditions();
672         $ci->add_grade_condition($gradeitemid, null, null, true);
673         $this->assertFalse($ci->is_available($text));
674         $this->assertEquals(get_string('requires_grade_any', 'condition', 'frog'), $text);
676         // Grade: Fake it existing
677         $DB->insert_record('grade_grades', (object)array(
678             'itemid' => $gradeitemid, 'userid' => $USER->id, 'finalgrade' => 3.78));
679         condition_info_section::wipe_session_cache();
680         $this->assertTrue($ci->is_available($text));
681         condition_info_section::wipe_session_cache();
682         $this->assertTrue($ci->is_available($text, true));
684         // Grade: Now require that user gets more than 3.78001
685         $ci->wipe_conditions();
686         $ci->add_grade_condition($gradeitemid, 3.78001, null, true);
687         condition_info_section::wipe_session_cache();
688         $this->assertFalse($ci->is_available($text));
689         $this->assertEquals(get_string('requires_grade_min', 'condition', 'frog'), $text);
691         // Grade: ...just on 3.78...
692         $ci->wipe_conditions();
693         $ci->add_grade_condition($gradeitemid, 3.78, null, true);
694         condition_info_section::wipe_session_cache();
695         $this->assertTrue($ci->is_available($text));
697         // Grade: ...less than 3.78
698         $ci->wipe_conditions();
699         $ci->add_grade_condition($gradeitemid, null, 3.78, true);
700         condition_info_section::wipe_session_cache();
701         $this->assertFalse($ci->is_available($text));
702         $this->assertEquals(get_string('requires_grade_max', 'condition', 'frog'), $text);
704         // Grade: ...less than 3.78001
705         $ci->wipe_conditions();
706         $ci->add_grade_condition($gradeitemid, null, 3.78001, true);
707         condition_info_section::wipe_session_cache();
708         $this->assertTrue($ci->is_available($text));
710         // Grade: ...in a range that includes it
711         $ci->wipe_conditions();
712         $ci->add_grade_condition($gradeitemid, 3, 4, true);
713         condition_info_section::wipe_session_cache();
714         $this->assertTrue($ci->is_available($text));
716         // Grade: ...in a range that doesn't include it
717         $ci->wipe_conditions();
718         $ci->add_grade_condition($gradeitemid, 4, 5, true);
719         condition_info_section::wipe_session_cache();
720         $this->assertFalse($ci->is_available($text));
721         $this->assertEquals(get_string('requires_grade_range', 'condition', 'frog'), $text);
723         // Grouping: Not member
724         $groupingid = $this->make_grouping($courseid, 'Grouping');
725         $groupid = $this->make_group($courseid, 'Group', $groupingid);
726         $sectionid = $this->make_section($courseid, array(), 6, array('groupingid' => $groupingid));
727         $ci = new condition_info_section((object)array('id' => $sectionid),
728                 CONDITION_MISSING_EVERYTHING);
729         $this->assertFalse($ci->is_available($text));
730         $this->assertEquals(trim(get_string('groupingnoaccess', 'condition')), $text);
732         // Grouping: Member
733         $this->assertTrue(groups_add_member($groupid, $USER->id));
735         condition_info_section::init_global_cache();
736         $this->assertTrue($ci->is_available($text));
737         $this->assertEquals('', $text);
738         $this->assertTrue($ci->is_available($text, true));
740         // Grouping: Somebody else
741         $this->assertFalse($ci->is_available($text, false, $USER->id + 1));
742         $this->assertFalse($ci->is_available($text, true, $USER->id + 1));
743     }