MDL-36721 make upgrade queries cross-db
[moodle.git] / lib / tests / conditionlib_test.php
blobe879df6e11146af61b0da8a7b049549c2c359936
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.
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
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
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);
48 function test_constructor() {
49 global $DB,$CFG;
50 $cm=new stdClass;
52 // Test records
53 $id=$DB->insert_record('course_modules',(object)array(
54 'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,'course'=>64));
56 // no ID
57 try {
58 $test=new condition_info($cm);
59 $this->fail();
60 } catch(coding_exception $e) {
63 // no other data
64 $cm->id=$id;
65 $test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
66 $this->assertEquals(
67 (object)array('id'=>$id,'showavailability'=>1,
68 'availablefrom'=>17,'availableuntil'=>398,'course'=>64,
69 'conditionsgrade'=>array(), 'conditionscompletion'=>array(),
70 'visible' => 1, 'conditionsfield' => array()),
71 $test->get_full_course_module());
73 // just the course_modules stuff; check it doesn't request that from db
74 $cm->showavailability=0;
75 $cm->availablefrom=2;
76 $cm->availableuntil=74;
77 $cm->course=38;
78 $cm->visible = 1;
79 $test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE);
80 $this->assertEquals(
81 (object)array('id'=>$id,'showavailability'=>0,
82 'availablefrom'=>2,'availableuntil'=>74,'course'=>38,
83 'conditionsgrade' => array(), 'conditionscompletion' => array(),
84 'visible' => 1, 'conditionsfield' => array()),
85 $test->get_full_course_module());
87 // Now let's add some actual grade/completion conditions
88 $DB->insert_record('course_modules_availability',(object)array(
89 'coursemoduleid'=>$id,
90 'sourcecmid'=>42,
91 'requiredcompletion'=>2
92 ));
93 $DB->insert_record('course_modules_availability',(object)array(
94 'coursemoduleid'=>$id,
95 'sourcecmid'=>666,
96 'requiredcompletion'=>1
97 ));
98 $DB->insert_record('course_modules_availability',(object)array(
99 'coursemoduleid'=>$id,
100 'gradeitemid'=>37,
101 'grademin'=>5.5
104 $cm=(object)array('id'=>$id);
105 $test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
106 $fullcm=$test->get_full_course_module();
107 $this->assertEquals(array(42=>2,666=>1),$fullcm->conditionscompletion);
108 $this->assertEquals(array(37=>(object)array('min'=>5.5,'max'=>null,'name'=>'!missing')),
109 $fullcm->conditionsgrade);
113 * Same as above test but for course_sections instead of course_modules.
115 public function test_section_constructor() {
116 global $DB, $CFG;
118 // Test records
119 $id = $DB->insert_record('course_sections', (object)array(
120 'showavailability' => 1, 'availablefrom' => 17,
121 'availableuntil' => 398, 'course' => 64, 'groupingid' => 13));
123 // No ID
124 $section = new stdClass;
125 try {
126 $test = new condition_info_section($section);
127 $this->fail();
128 } catch (coding_exception $e) {
129 // Do nothing
132 // No other data
133 $section->id = $id;
134 $test = new condition_info_section($section, CONDITION_MISSING_EVERYTHING);
135 $this->assertEquals(
136 (object)array('id' => $id, 'showavailability' => 1, 'groupingid' => 13,
137 'availablefrom' => 17, 'availableuntil' => 398, 'course' => 64,
138 'conditionsgrade' => array(), 'conditionscompletion' => array(),
139 'visible' => 1, 'conditionsfield' => array()),
140 $test->get_full_section());
142 // Just the course_sections stuff; check it doesn't request that from db
143 // (by using fake values and ensuring it still has those)
144 $section->showavailability = 0;
145 $section->availablefrom = 2;
146 $section->availableuntil = 74;
147 $section->course = 38;
148 $section->groupingid = 99;
149 $section->visible = 1;
150 $test = new condition_info_section($section, CONDITION_MISSING_EXTRATABLE);
151 $this->assertEquals(
152 (object)array('id' => $id, 'showavailability' => 0, 'groupingid' => 99,
153 'availablefrom' => 2, 'availableuntil' => 74, 'course' => 38,
154 'conditionsgrade' => array(), 'conditionscompletion' => array(),
155 'visible' => 1, 'conditionsfield' => array()),
156 $test->get_full_section());
158 // Now let's add some actual grade/completion conditions
159 $DB->insert_record('course_sections_availability', (object)array(
160 'coursesectionid' => $id,
161 'sourcecmid' => 42,
162 'requiredcompletion' => 2
164 $DB->insert_record('course_sections_availability', (object)array(
165 'coursesectionid' => $id,
166 'sourcecmid' => 666,
167 'requiredcompletion' => 1
169 $DB->insert_record('course_sections_availability', (object)array(
170 'coursesectionid' => $id,
171 'gradeitemid' => 37,
172 'grademin' => 5.5
175 $section = (object)array('id' => $id);
176 $test = new condition_info_section($section, CONDITION_MISSING_EVERYTHING);
177 $fullsection = $test->get_full_section();
178 $this->assertEquals(array(42 => 2, 666 => 1), $fullsection->conditionscompletion);
179 $this->assertEquals(array(37 => (object)array('min' => 5.5, 'max' => null, 'name' => '!missing')),
180 $fullsection->conditionsgrade);
183 private function make_course() {
184 global $DB;
185 $categoryid = $DB->insert_record('course_categories', (object)array('name'=>'conditionlibtest'));
186 $courseid = $DB->insert_record('course', (object)array(
187 'fullname'=>'Condition test','shortname'=>'CT1',
188 'category'=>$categoryid,'enablecompletion'=>1));
189 context_course::instance($courseid);
190 return $courseid;
193 private function make_course_module($courseid,$params=array()) {
194 global $DB;
195 static $moduleid=0;
196 if(!$moduleid) {
197 $moduleid=$DB->get_field('modules','id',array('name'=>'resource'));
200 $rid=$DB->insert_record('resource',(object)array('course'=>$courseid,
201 'name'=>'xxx','alltext'=>'','popup'=>''));
202 $settings=(object)array(
203 'course'=>$courseid,'module'=>$moduleid,'instance'=>$rid);
204 foreach($params as $name=>$value) {
205 $settings->{$name}=$value;
207 $cmid = $DB->insert_record('course_modules', $settings);
208 rebuild_course_cache($courseid, true);
209 return $cmid;
212 private function make_section($courseid, $cmids, $sectionnum=0, $params=array()) {
213 global $DB;
214 $record = (object)array(
215 'course' => $courseid,
216 'sequence' => implode(',', $cmids),
217 'section' => $sectionnum);
218 foreach ($params as $name => $value) {
219 $record->{$name} = $value;
221 $sectionid = $DB->insert_record('course_sections', $record);
222 rebuild_course_cache($courseid, true);
223 return $sectionid;
226 private function make_grouping($courseid, $name) {
227 global $CFG;
228 require_once($CFG->dirroot . '/group/lib.php');
229 return groups_create_grouping((object)array('courseid' => $courseid,
230 'name' => $name));
233 private function make_group($courseid, $name, $groupingid=0) {
234 global $CFG;
235 require_once($CFG->dirroot . '/group/lib.php');
236 $groupid = groups_create_group((object)array('courseid' => $courseid,
237 'name' => $name));
238 if ($groupingid) {
239 groups_assign_grouping($groupingid, $groupid);
241 return $groupid;
244 function test_modinfo() {
245 global $DB;
247 // Let's make a course
248 $courseid=$this->make_course();
250 // Now let's make a couple modules on that course
251 $cmid1=$this->make_course_module($courseid,array(
252 'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,
253 'completion'=>COMPLETION_TRACKING_MANUAL));
254 $cmid2=$this->make_course_module($courseid,array(
255 'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
256 $this->make_section($courseid,array($cmid1,$cmid2));
258 // Add a fake grade item
259 $gradeitemid=$DB->insert_record('grade_items',(object)array(
260 'courseid'=>$courseid,'itemname'=>'frog'));
262 // One of the modules has grade and completion conditions, other doesn't
263 $DB->insert_record('course_modules_availability',(object)array(
264 'coursemoduleid'=>$cmid2,
265 'sourcecmid'=>$cmid1,
266 'requiredcompletion'=>1
268 $DB->insert_record('course_modules_availability',(object)array(
269 'coursemoduleid'=>$cmid2,
270 'gradeitemid'=>$gradeitemid,
271 'grademin'=>5.5
274 // Okay sweet, now get modinfo
275 $modinfo=get_fast_modinfo($courseid);
277 // Test basic data
278 $this->assertEquals(1,$modinfo->cms[$cmid1]->showavailability);
279 $this->assertEquals(17,$modinfo->cms[$cmid1]->availablefrom);
280 $this->assertEquals(398,$modinfo->cms[$cmid1]->availableuntil);
281 $this->assertEquals(0,$modinfo->cms[$cmid2]->showavailability);
282 $this->assertEquals(0,$modinfo->cms[$cmid2]->availablefrom);
283 $this->assertEquals(0,$modinfo->cms[$cmid2]->availableuntil);
285 // Test condition arrays
286 $this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionscompletion);
287 $this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionsgrade);
288 $this->assertEquals(array($cmid1=>1),
289 $modinfo->cms[$cmid2]->conditionscompletion);
290 $this->assertEquals(array($gradeitemid=>(object)array('min'=>5.5,'max'=>null,'name'=>'frog')),
291 $modinfo->cms[$cmid2]->conditionsgrade);
294 public function test_section_modinfo() {
295 global $DB;
297 // Let's make a course
298 $courseid = $this->make_course();
300 // Now let's make a couple sections on that course, one of which has a cm
301 $cmid = $this->make_course_module($courseid);
302 $sectionid1 = $this->make_section($courseid, array($cmid), 1, array(
303 'showavailability' => 1, 'availablefrom' => 17,
304 'availableuntil' => 398, 'groupingid' => 13));
305 $sectionid2 = $this->make_section($courseid, array(), 2);
307 // Add a fake grade item
308 $gradeitemid = $DB->insert_record('grade_items', (object)array(
309 'courseid' => $courseid, 'itemname' => 'frog'));
311 // One of the sections has grade and completion conditions, other doesn't
312 $DB->insert_record('course_sections_availability', (object)array(
313 'coursesectionid' => $sectionid2,
314 'sourcecmid' => $cmid,
315 'requiredcompletion'=>1
317 $DB->insert_record('course_sections_availability', (object)array(
318 'coursesectionid' => $sectionid2,
319 'gradeitemid' => $gradeitemid,
320 'grademin' => 5.5
323 rebuild_course_cache($courseid, true);
324 // Okay sweet, now get modinfo
325 $modinfo = get_fast_modinfo($courseid);
327 // Test basic data
328 $section1 = $modinfo->get_section_info(1);
329 $this->assertEquals(1, $section1->showavailability);
330 $this->assertEquals(17, $section1->availablefrom);
331 $this->assertEquals(398, $section1->availableuntil);
332 $this->assertEquals(13, $section1->groupingid);
333 $section2 = $modinfo->get_section_info(2);
334 $this->assertEquals(0, $section2->showavailability);
335 $this->assertEquals(0, $section2->availablefrom);
336 $this->assertEquals(0, $section2->availableuntil);
337 $this->assertEquals(0, $section2->groupingid);
339 // Test condition arrays
340 $this->assertEquals(array(), $section1->conditionscompletion);
341 $this->assertEquals(array(), $section1->conditionsgrade);
342 $this->assertEquals(array($cmid => 1),
343 $section2->conditionscompletion);
344 $this->assertEquals(array($gradeitemid => (object)array('min' => 5.5, 'max' => null, 'name' => 'frog')),
345 $section2->conditionsgrade);
348 function test_add_and_remove() {
349 global $DB;
350 // Make course and module
351 $courseid=$this->make_course();
352 $cmid=$this->make_course_module($courseid,array(
353 'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
354 $this->make_section($courseid,array($cmid));
356 // Check it has no conditions
357 $test1=new condition_info((object)array('id'=>$cmid),
358 CONDITION_MISSING_EVERYTHING);
359 $cm=$test1->get_full_course_module();
360 $this->assertEquals(array(),$cm->conditionscompletion);
361 $this->assertEquals(array(),$cm->conditionsgrade);
363 // Add conditions of each type
364 $test1->add_completion_condition(13,3);
365 $this->assertEquals(array(13=>3),$cm->conditionscompletion);
366 $test1->add_grade_condition(666,0.4,null,true);
367 $this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
368 $cm->conditionsgrade);
370 // Check they were really added in db
371 $test2=new condition_info((object)array('id'=>$cmid),
372 CONDITION_MISSING_EVERYTHING);
373 $cm=$test2->get_full_course_module();
374 $this->assertEquals(array(13=>3),$cm->conditionscompletion);
375 $this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
376 $cm->conditionsgrade);
378 // Wipe conditions
379 $test2->wipe_conditions();
380 $this->assertEquals(array(),$cm->conditionscompletion);
381 $this->assertEquals(array(),$cm->conditionsgrade);
383 // Check they were really wiped
384 $test3=new condition_info((object)array('id'=>$cmid),
385 CONDITION_MISSING_EVERYTHING);
386 $cm=$test3->get_full_course_module();
387 $this->assertEquals(array(),$cm->conditionscompletion);
388 $this->assertEquals(array(),$cm->conditionsgrade);
391 public function test_section_add_and_remove() {
392 global $DB;
394 // Make course and module
395 $courseid = $this->make_course();
396 $cmid = $this->make_course_module($courseid);
397 $sectionid = $this->make_section($courseid, array($cmid));
399 // Check it has no conditions
400 $test1 = new condition_info_section((object)array('id'=>$sectionid),
401 CONDITION_MISSING_EVERYTHING);
402 $section = $test1->get_full_section();
403 $this->assertEquals(array(), $section->conditionscompletion);
404 $this->assertEquals(array(), $section->conditionsgrade);
406 // Add conditions of each type
407 $test1->add_completion_condition(13, 3);
408 $this->assertEquals(array(13 => 3), $section->conditionscompletion);
409 $test1->add_grade_condition(666, 0.4, null, true);
410 $this->assertEquals(array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing')),
411 $section->conditionsgrade);
413 // Check they were really added in db
414 $test2 = new condition_info_section((object)array('id' => $sectionid),
415 CONDITION_MISSING_EVERYTHING);
416 $section = $test2->get_full_section();
417 $this->assertEquals(array(13 => 3), $section->conditionscompletion);
418 $this->assertEquals(array(666 => (object)array('min' => 0.4, 'max' => null, 'name' => '!missing')),
419 $section->conditionsgrade);
421 // Wipe conditions
422 $test2->wipe_conditions();
423 $this->assertEquals(array(), $section->conditionscompletion);
424 $this->assertEquals(array(), $section->conditionsgrade);
426 // Check they were really wiped
427 $test3 = new condition_info_section((object)array('id' => $cmid),
428 CONDITION_MISSING_EVERYTHING);
429 $section = $test3->get_full_section();
430 $this->assertEquals(array(), $section->conditionscompletion);
431 $this->assertEquals(array(), $section->conditionsgrade);
434 function test_is_available() {
435 global $DB,$USER;
436 $courseid=$this->make_course();
438 // No conditions
439 $cmid=$this->make_course_module($courseid);
440 $ci=new condition_info((object)array('id'=>$cmid),
441 CONDITION_MISSING_EVERYTHING);
442 $this->assertTrue($ci->is_available($text,false,0));
443 $this->assertEquals('',$text);
445 // Time (from)
446 $time=time()+100;
447 $cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
448 $ci=new condition_info((object)array('id'=>$cmid),
449 CONDITION_MISSING_EVERYTHING);
450 $this->assertFalse($ci->is_available($text));
451 $this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$text);
453 $time=time()-100;
454 $cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
455 $ci=new condition_info((object)array('id'=>$cmid),
456 CONDITION_MISSING_EVERYTHING);
457 $this->assertTrue($ci->is_available($text));
458 $this->assertEquals('',$text);
459 $this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$ci->get_full_information());
461 // Time (until)
462 $cmid=$this->make_course_module($courseid,array('availableuntil'=>time()-100));
463 $ci=new condition_info((object)array('id'=>$cmid),
464 CONDITION_MISSING_EVERYTHING);
465 $this->assertFalse($ci->is_available($text));
466 $this->assertEquals('',$text);
468 // Completion
469 $oldid=$cmid;
470 $cmid=$this->make_course_module($courseid);
471 $this->make_section($courseid,array($oldid,$cmid));
472 $oldcm=$DB->get_record('course_modules',array('id'=>$oldid));
473 $oldcm->completion=COMPLETION_TRACKING_MANUAL;
474 $DB->update_record('course_modules',$oldcm);
476 // Need to reset modinfo after changing the options
477 rebuild_course_cache($courseid);
479 $ci=new condition_info((object)array('id'=>$cmid),CONDITION_MISSING_EVERYTHING);
480 $ci->add_completion_condition($oldid,COMPLETION_COMPLETE);
481 condition_info::wipe_session_cache();
483 $this->assertFalse($ci->is_available($text,false));
484 $this->assertEquals(get_string('requires_completion_1','condition','xxx'),$text);
485 completion_info::wipe_session_cache();
486 $completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
487 $completion->update_state($oldcm,COMPLETION_COMPLETE);
488 completion_info::wipe_session_cache();
489 condition_info::wipe_session_cache();
491 $this->assertTrue($ci->is_available($text));
492 $this->assertFalse($ci->is_available($text,false,$USER->id+1));
493 completion_info::wipe_session_cache();
494 condition_info::wipe_session_cache();
495 $completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
496 $completion->update_state($oldcm,COMPLETION_INCOMPLETE);
497 $this->assertFalse($ci->is_available($text));
499 $ci->wipe_conditions();
500 $ci->add_completion_condition($oldid,COMPLETION_INCOMPLETE);
501 condition_info::wipe_session_cache();
502 $this->assertTrue($ci->is_available($text));
503 $this->assertTrue($ci->is_available($text,false,$USER->id+1));
505 condition_info::wipe_session_cache();
506 $this->assertTrue($ci->is_available($text,true));
508 // Grade
509 $ci->wipe_conditions();
510 // Add a fake grade item
511 $gradeitemid=$DB->insert_record('grade_items',(object)array(
512 'courseid'=>$courseid,'itemname'=>'frog'));
513 // Add a condition on a value existing...
514 $ci->add_grade_condition($gradeitemid,null,null,true);
515 $this->assertFalse($ci->is_available($text));
516 $this->assertEquals(get_string('requires_grade_any','condition','frog'),$text);
518 // Fake it existing
519 $DB->insert_record('grade_grades',(object)array(
520 'itemid'=>$gradeitemid,'userid'=>$USER->id,'finalgrade'=>3.78));
521 condition_info::wipe_session_cache();
522 $this->assertTrue($ci->is_available($text));
524 condition_info::wipe_session_cache();
525 $this->assertTrue($ci->is_available($text,true));
527 // Now require that user gets more than 3.78001
528 $ci->wipe_conditions();
529 $ci->add_grade_condition($gradeitemid,3.78001,null,true);
530 condition_info::wipe_session_cache();
531 $this->assertFalse($ci->is_available($text));
532 $this->assertEquals(get_string('requires_grade_min','condition','frog'),$text);
534 // ...just on 3.78...
535 $ci->wipe_conditions();
536 $ci->add_grade_condition($gradeitemid,3.78,null,true);
537 condition_info::wipe_session_cache();
538 $this->assertTrue($ci->is_available($text));
540 // ...less than 3.78
541 $ci->wipe_conditions();
542 $ci->add_grade_condition($gradeitemid,null,3.78,true);
543 condition_info::wipe_session_cache();
544 $this->assertFalse($ci->is_available($text));
545 $this->assertEquals(get_string('requires_grade_max','condition','frog'),$text);
547 // ...less than 3.78001
548 $ci->wipe_conditions();
549 $ci->add_grade_condition($gradeitemid,null,3.78001,true);
550 condition_info::wipe_session_cache();
551 $this->assertTrue($ci->is_available($text));
553 // ...in a range that includes it
554 $ci->wipe_conditions();
555 $ci->add_grade_condition($gradeitemid,3,4,true);
556 condition_info::wipe_session_cache();
557 $this->assertTrue($ci->is_available($text));
559 // ...in a range that doesn't include it
560 $ci->wipe_conditions();
561 $ci->add_grade_condition($gradeitemid,4,5,true);
562 condition_info::wipe_session_cache();
563 $this->assertFalse($ci->is_available($text));
564 $this->assertEquals(get_string('requires_grade_range','condition','frog'),$text);
567 public function test_section_is_available() {
568 global $DB, $USER;
569 $courseid = $this->make_course();
571 // Enrol user (needed for groups)
572 $enrolplugin = enrol_get_plugin('manual');
573 $course = $DB->get_record('course', array('id' => $courseid));
574 $enrolplugin->add_instance($course);
575 $enrolinstances = enrol_get_instances($courseid, false);
576 foreach ($enrolinstances as $enrolinstance) {
577 if ($enrolinstance->enrol === 'manual') {
578 break;
581 $enrolplugin->enrol_user($enrolinstance, $USER->id);
583 // Module for conditions later
584 $cmid = $this->make_course_module($courseid);
586 // No conditions
587 $sectionid = $this->make_section($courseid, array($cmid), 1);
588 $ci = new condition_info_section((object)array('id' => $sectionid),
589 CONDITION_MISSING_EVERYTHING);
590 $this->assertTrue($ci->is_available($text, false, 0));
591 $this->assertEquals('', $text);
593 // Time (from)
594 $time = time() + 100;
595 $sectionid = $this->make_section($courseid, array(), 2, array('availablefrom' => $time));
596 $ci = new condition_info_section((object)array('id' => $sectionid),
597 CONDITION_MISSING_EVERYTHING);
598 $this->assertFalse($ci->is_available($text));
599 $timetext = userdate($time, get_string('strftimedate', 'langconfig'));
600 $this->assertRegExp('~' . preg_quote($timetext) . '~', $text);
602 $time=time()-100;
603 $sectionid = $this->make_section($courseid, array(), 3, array('availablefrom' => $time));
604 $ci = new condition_info_section((object)array('id' => $sectionid),
605 CONDITION_MISSING_EVERYTHING);
606 $this->assertTrue($ci->is_available($text));
607 $this->assertEquals('', $text);
608 $timetext = userdate($time, get_string('strftimedate', 'langconfig'));
609 $this->assertRegExp('~' . preg_quote($timetext) . '~', $ci->get_full_information());
611 // Time (until)
612 $sectionid = $this->make_section($courseid, array(), 4, array('availableuntil' => time() - 100));
613 $ci = new condition_info_section((object)array('id' => $sectionid),
614 CONDITION_MISSING_EVERYTHING);
615 $this->assertFalse($ci->is_available($text));
616 $this->assertEquals('', $text);
618 // Completion: first set up cm
619 $sectionid = $this->make_section($courseid, array(), 5);
620 $cm = $DB->get_record('course_modules', array('id' => $cmid));
621 $cm->completion = COMPLETION_TRACKING_MANUAL;
622 $DB->update_record('course_modules', $cm);
624 // Completion: Reset modinfo after changing the options
625 rebuild_course_cache($courseid);
627 // Completion: Add condition
628 $ci = new condition_info_section((object)array('id' => $sectionid),
629 CONDITION_MISSING_EVERYTHING);
630 $ci->add_completion_condition($cmid, COMPLETION_COMPLETE);
631 condition_info_section::wipe_session_cache();
633 // Completion: Check
634 $this->assertFalse($ci->is_available($text, false));
635 $this->assertEquals(get_string('requires_completion_1', 'condition', 'xxx'), $text);
636 completion_info::wipe_session_cache();
637 $completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
638 $completion->update_state($cm, COMPLETION_COMPLETE);
639 completion_info::wipe_session_cache();
640 condition_info_section::wipe_session_cache();
641 $this->assertTrue($ci->is_available($text));
642 $this->assertFalse($ci->is_available($text, false, $USER->id + 1));
644 // Completion: Uncheck
645 completion_info::wipe_session_cache();
646 condition_info_section::wipe_session_cache();
647 $completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
648 $completion->update_state($cm, COMPLETION_INCOMPLETE);
649 $this->assertFalse($ci->is_available($text));
651 // Completion: Incomplete condition
652 $ci->wipe_conditions();
653 $ci->add_completion_condition($cmid, COMPLETION_INCOMPLETE);
654 condition_info_section::wipe_session_cache();
655 $this->assertTrue($ci->is_available($text));
656 $this->assertTrue($ci->is_available($text, false, $USER->id + 1));
657 condition_info_section::wipe_session_cache();
658 $this->assertTrue($ci->is_available($text, true));
660 // Grade: Add a fake grade item
661 $gradeitemid = $DB->insert_record('grade_items', (object)array(
662 'courseid' => $courseid, 'itemname' => 'frog'));
664 // Grade: Add a condition on a value existing
665 $ci->wipe_conditions();
666 $ci->add_grade_condition($gradeitemid, null, null, true);
667 $this->assertFalse($ci->is_available($text));
668 $this->assertEquals(get_string('requires_grade_any', 'condition', 'frog'), $text);
670 // Grade: Fake it existing
671 $DB->insert_record('grade_grades', (object)array(
672 'itemid' => $gradeitemid, 'userid' => $USER->id, 'finalgrade' => 3.78));
673 condition_info_section::wipe_session_cache();
674 $this->assertTrue($ci->is_available($text));
675 condition_info_section::wipe_session_cache();
676 $this->assertTrue($ci->is_available($text, true));
678 // Grade: Now require that user gets more than 3.78001
679 $ci->wipe_conditions();
680 $ci->add_grade_condition($gradeitemid, 3.78001, null, true);
681 condition_info_section::wipe_session_cache();
682 $this->assertFalse($ci->is_available($text));
683 $this->assertEquals(get_string('requires_grade_min', 'condition', 'frog'), $text);
685 // Grade: ...just on 3.78...
686 $ci->wipe_conditions();
687 $ci->add_grade_condition($gradeitemid, 3.78, null, true);
688 condition_info_section::wipe_session_cache();
689 $this->assertTrue($ci->is_available($text));
691 // Grade: ...less than 3.78
692 $ci->wipe_conditions();
693 $ci->add_grade_condition($gradeitemid, null, 3.78, true);
694 condition_info_section::wipe_session_cache();
695 $this->assertFalse($ci->is_available($text));
696 $this->assertEquals(get_string('requires_grade_max', 'condition', 'frog'), $text);
698 // Grade: ...less than 3.78001
699 $ci->wipe_conditions();
700 $ci->add_grade_condition($gradeitemid, null, 3.78001, true);
701 condition_info_section::wipe_session_cache();
702 $this->assertTrue($ci->is_available($text));
704 // Grade: ...in a range that includes it
705 $ci->wipe_conditions();
706 $ci->add_grade_condition($gradeitemid, 3, 4, true);
707 condition_info_section::wipe_session_cache();
708 $this->assertTrue($ci->is_available($text));
710 // Grade: ...in a range that doesn't include it
711 $ci->wipe_conditions();
712 $ci->add_grade_condition($gradeitemid, 4, 5, true);
713 condition_info_section::wipe_session_cache();
714 $this->assertFalse($ci->is_available($text));
715 $this->assertEquals(get_string('requires_grade_range', 'condition', 'frog'), $text);
717 // Grouping: Not member
718 $groupingid = $this->make_grouping($courseid, 'Grouping');
719 $groupid = $this->make_group($courseid, 'Group', $groupingid);
720 $sectionid = $this->make_section($courseid, array(), 6, array('groupingid' => $groupingid));
721 $ci = new condition_info_section((object)array('id' => $sectionid),
722 CONDITION_MISSING_EVERYTHING);
723 $this->assertFalse($ci->is_available($text));
724 $this->assertEquals(trim(get_string('groupingnoaccess', 'condition')), $text);
726 // Grouping: Member
727 $this->assertTrue(groups_add_member($groupid, $USER->id));
729 condition_info_section::init_global_cache();
730 $this->assertTrue($ci->is_available($text));
731 $this->assertEquals('', $text);
732 $this->assertTrue($ci->is_available($text, true));
734 // Grouping: Somebody else
735 $this->assertFalse($ci->is_available($text, false, $USER->id + 1));
736 $this->assertFalse($ci->is_available($text, true, $USER->id + 1));
740 * Tests user fields to ensure that the list of provided fields includes only
741 * fields which the equivalent function can be used to obtain the value of.
743 public function test_condition_user_fields() {
744 global $CFG, $DB, $USER;
746 // Set up basic data.
747 $courseid = $this->make_course();
748 $cmid = $this->make_course_module($courseid);
749 $ci = new condition_info_testwrapper(
750 (object)array('id' => $cmid), CONDITION_MISSING_EVERYTHING);
752 // Add a custom user profile field. Unfortunately there is no back-end
753 // API for adding profile fields without having an actual form and doing
754 // redirects and stuff! These are the default text field parameters.
755 require_once($CFG->dirroot . '/user/profile/lib.php');
756 $field = (object)array(
757 'shortname' => 'myfield', 'name' => 'My field', 'required' => 0,
758 'locked' => 0, 'forceunique' => 0, 'signup' => 0,
759 'visible' => PROFILE_VISIBLE_ALL,
760 'datatype' => 'text', 'description' => 'A field of mine',
761 'descriptionformat' => FORMAT_HTML, 'defaultdata' => '',
762 'defaultdataformat' => FORMAT_HTML, 'param1' => 30, 'param2' => 2048,
763 'param3' => 0, 'param4' => '', 'param5' => '');
764 $customfieldid = $DB->insert_record('user_info_field', $field);
766 // Get list of condition user fields.
767 $fields = condition_info::get_condition_user_fields();
769 // Check custom field is included.
770 $this->assertEquals('My field', $fields[$customfieldid]);
772 // For all other fields, check it actually works to get data from them.
773 foreach ($fields as $fieldid => $name) {
774 // Not checking the result, just that it's possible to get it
775 // without error.
776 $ci->get_cached_user_profile_field($USER->id, $fieldid);
779 // Change to not logged in user.
780 $this->setUser(null);
782 foreach ($fields as $fieldid => $name) {
783 // Should get false always when not logged in.
784 $this->assertEquals(false, $ci->get_cached_user_profile_field($USER->id, $fieldid));
792 * Test wrapper used only to make protected functions public so they can be
793 * tested.
795 class condition_info_testwrapper extends condition_info {
796 public function get_cached_user_profile_field($userid, $fieldid) {
797 return parent::get_cached_user_profile_field($userid, $fieldid);