Index: admin/settings/misc.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/admin/settings/misc.php,v retrieving revision 1.13 diff -u -r1.13 misc.php --- admin/settings/misc.php 17 Nov 2008 11:06:04 -0000 1.13 +++ admin/settings/misc.php 18 Dec 2008 17:42:48 -0000 @@ -19,6 +19,11 @@ $temp->add(new admin_setting_configcheckbox('enablecompletion',get_string('enablecompletion','completion'),get_string('configenablecompletion','completion'),COMPLETION_ENABLED)); $temp->add(new admin_setting_pickroles('progresstrackedroles',get_string('progresstrackedroles','completion'),get_string('configprogresstrackedroles','completion'))); + // Conditional availability + $temp->add(new admin_setting_configcheckbox('enableavailability', + get_string('enableavailability','condition'), + get_string('configenableavailability','condition'), 0)); + // HTML editor config $temp->add(new admin_setting_configtext('htmledstoresize',get_string('htmleditorstoresize','admin'),get_string('htmleditorstoresized','admin'), '104857600',PARAM_INT, 10)); $temp->add(new admin_setting_configtextarea('htmledtypeimage',get_string('htmleditortypeimage','admin'),get_string('htmleditortypeimaged','admin'),'gif, jpg, jpeg, png',PARAM_TEXT,'60','2')); Index: lib/datalib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/lib/datalib.php,v retrieving revision 1.93 diff -u -r1.93 datalib.php --- lib/datalib.php 9 Dec 2008 15:10:00 -0000 1.93 +++ lib/datalib.php 18 Dec 2008 17:42:49 -0000 @@ -2158,7 +2158,9 @@ * @return bool */ function coursemodule_visible_for_user($cm, $userid=0) { - global $USER; +// ou-specific begins (until 2.0) + global $USER,$CFG; +// ou-specific ends (until 2.0) if (empty($cm->id)) { debugging("Incorrect course module parameter!", DEBUG_DEVELOPER); @@ -2170,6 +2172,17 @@ if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $cm->id), $userid)) { return false; } +// ou-specific begins (until 2.0) + if ($CFG->enableavailability) { + require_once($CFG->libdir.'/conditionlib.php'); + $ci=new condition_info($cm,CONDITION_MISSING_EXTRATABLE); + if(!$ci->is_available($cm->availableinfo,false,$userid) and + !has_capability('moodle/course:viewhiddenactivities', + get_context_instance(CONTEXT_MODULE, $cm->id), $userid)) { + return false; + } + } +// ou-specific ends (until 2.0) return groups_course_module_visible($cm, $userid); } Index: lib/completionlib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/lib/completionlib.php,v retrieving revision 1.6 diff -u -r1.6 completionlib.php --- lib/completionlib.php 13 Nov 2008 13:30:53 -0000 1.6 +++ lib/completionlib.php 18 Dec 2008 17:42:49 -0000 @@ -358,16 +358,20 @@ * session cache if available, or by SQL query) * * @param object $course Course - * @param object $cm Activity + * @param object $cm Activity; only required field is ->id * @param bool $wholecourse If true (default false) then, when necessary to * fill the cache, retrieves information from the entire course not just for * this one activity * @param int $userid User ID or 0 (default) for current user + * @param array $modinfo Supply the value here - this is used for unit + * testing and so that it can be called recursively from within + * get_fast_modinfo. (Needs only list of all CMs with IDs.) + * Otherwise the method calls get_fast_modinfo itself. * @return object Completion data (record from course_modules_completion) * @throws Exception In some cases where the requested course-module is not * found on the specified course */ -function completion_get_data($course,$cm,$wholecourse=false,$userid=0) { +function completion_get_data($course,$cm,$wholecourse=false,$userid=0,$modinfo=null) { // Get user ID global $USER,$CFG,$SESSION; if(!$userid) { @@ -417,7 +421,9 @@ } // Get the module info and build up condition info for each one - $modinfo=get_fast_modinfo($course,$userid); + if(!$modinfo) { + $modinfo=get_fast_modinfo($course,$userid); + } foreach($modinfo->cms as $othercm) { if(array_key_exists($othercm->id,$alldata)) { $data=$alldata[$othercm->id]; Index: lib/moodlelib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/lib/moodlelib.php,v retrieving revision 1.138 diff -u -r1.138 moodlelib.php --- lib/moodlelib.php 2 Dec 2008 14:31:13 -0000 1.138 +++ lib/moodlelib.php 18 Dec 2008 17:42:49 -0000 @@ -2108,6 +2108,32 @@ $cm->visible = $accessible; } //ou-specific ends + +// ou-specific begins (until 2.0) + // Conditional activity access control + if(!empty($CFG->enableavailability) and $cm) { + // We cache conditional access in session + if(!isset($SESSION->conditionaccessok)) { + $SESSION->conditionaccessok=array(); + } + // If you have been allowed into the module once then you are allowed + // in for rest of session, no need to do conditional checks + if(!array_key_exists($cm->id,$SESSION->conditionaccessok)) { + // Get condition info (does a query for the availability table) + require_once($CFG->libdir.'/conditionlib.php'); + $ci=new condition_info($cm,CONDITION_MISSING_EXTRATABLE); + // Check condition for user (this will do a query if the availability + // information depends on grade or completion information) + if($ci->is_available($junk) || + has_capability('moodle/course:viewhiddenactivities', $COURSE->context)) { + $SESSION->conditionaccessok[$cm->id]=true; + } else { + print_error('activityiscurrentlyhidden'); + } + } + } +// ou-specific ends (until 2.0) + if ($COURSE->id == SITEID) { /// Eliminate hidden site activities straight away if (!empty($cm) && !$cm->visible Index: course/moodleform_mod.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/course/moodleform_mod.php,v retrieving revision 1.27 diff -u -r1.27 moodleform_mod.php --- course/moodleform_mod.php 5 Nov 2008 09:26:48 -0000 1.27 +++ course/moodleform_mod.php 18 Dec 2008 17:42:49 -0000 @@ -1,5 +1,13 @@ libdir.'/formslib.php'); +// ou-specific begins (until 2.0) +if(!empty($CFG->enablecompletion)) { + require_once($CFG->libdir.'/completionlib.php'); +} +if(!empty($CFG->enableavailability)) { + require_once($CFG->libdir.'/conditionlib.php'); +} +// ou-specific ends (until 2.0) /** * This class adds extra methods to form wrapper specific to be used for module * add / update forms (mod/{modname}.mod_form.php replaces deprecated mod/{modname}/mod.html @@ -177,7 +185,34 @@ $mform->freeze($this->_customcompletionelements); } } -// ou-specific ends (until 2.0) + + // Availability conditions + if (!empty($CFG->enableavailability) && $this->_cm) { + $ci = new condition_info($this->_cm); + $fullcm=$ci->get_full_course_module(); + + $num=0; + foreach($fullcm->conditionsgrade as $gradeitemid=>$minmax) { + $groupelements=$mform->getElement('conditiongradegroup['.$num.']')->getElements(); + $groupelements[0]->setValue($gradeitemid); + // These numbers are always in the format 0.00000 - the rtrims remove any final zeros and, + // if it is a whole number, the decimal place. + $groupelements[2]->setValue(is_null($minmax->min)?'':rtrim(rtrim($minmax->min,'0'),'.')); + $groupelements[4]->setValue(is_null($minmax->max)?'':rtrim(rtrim($minmax->max,'0'),'.')); + $num++; + } + + if (completion_is_enabled($COURSE)) { + $num=0; + foreach($fullcm->conditionscompletion as $othercmid=>$state) { + $groupelements=$mform->getElement('conditioncompletiongroup['.$num.']')->getElements(); + $groupelements[0]->setValue($othercmid); + $groupelements[1]->setValue($state); + $num++; + } + } + } + // ou-specific ends (until 2.0) } @@ -377,10 +412,6 @@ $mform->disabledIf('parentcmid', 'stealth', 'selected', 1); } if (!$this->_features->repeatactivity) { - $mform->addElement('date_selector', 'livedate', get_string('livedate', 'module_access'),array('optional'=>true)); - $mform->setHelpButton('livedate', array('liveremovedate', get_string('help_liveremovedate', 'module_access'), 'module_access')); - $mform->addElement('date_selector', 'removedate', get_string('removedate', 'module_access'),array('optional'=>true)); - $mform->setHelpButton('removedate', array('liveremovedate', get_string('help_liveremovedate', 'module_access'), 'module_access')); $mform->addElement('text', 'showto', get_string('showto', 'module_access')); $mform->setHelpButton('showto', array('showto', get_string('help_showto', 'module_access'), 'module_access')); } @@ -398,8 +429,86 @@ } // ou-specific begins (until 2.0) + if (!empty($CFG->enableavailability)) { + // Conditional availability + $mform->addElement('header', '', get_string('availabilityconditions', 'condition')); + $mform->addElement('date_selector', 'availablefrom', get_string('availablefrom', 'condition'), array('optional'=>true)); + $mform->setHelpButton('availablefrom', array('conditiondates', get_string('help_conditiondates', 'condition'), 'condition')); + $mform->addElement('date_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true)); + $mform->setHelpButton('availableuntil', array('conditiondates', get_string('help_conditiondates', 'condition'), 'condition')); + + // Conditions based on grades + $gradeoptions=array(); + $items=grade_item::fetch_all(array('courseid'=>$COURSE->id)); + foreach($items as $id=>$item) { + $gradeoptions[$id]=$item->get_name(); + } + asort($gradeoptions); + $gradeoptions=array(0=>get_string('none','condition'))+$gradeoptions; + + $grouparray=array(); + $grouparray[] =& $mform->createElement('select','conditiongradeitemid','',$gradeoptions); + $grouparray[] =& $mform->createElement('static', '', '',' '.get_string('grade_atleast','condition')); + $grouparray[] =& $mform->createElement('text', 'conditiongrademin','',array('size'=>3)); + $grouparray[] =& $mform->createElement('static', '', '',' '.get_string('grade_upto','condition')); + $grouparray[] =& $mform->createElement('text', 'conditiongrademax','',array('size'=>3)); + $mform->setType('conditiongrademin',PARAM_NUMBER); + $mform->setType('conditiongrademax',PARAM_NUMBER); + $group = $mform->createElement('group','conditiongradegroup', + get_string('gradecondition', 'condition'),$grouparray); + + // Get version with condition info and store it so we don't ask + // twice + if(!empty($this->_cm)) { + $ci = new condition_info($this->_cm,CONDITION_MISSING_EXTRATABLE); + $this->_cm=$ci->get_full_course_module(); + $count=count($this->_cm->conditionsgrade)+1; + } else { + $count=1; + } + + $this->repeat_elements(array($group),$count,array(),'conditiongraderepeats','conditiongradeadds',2, + get_string('addgrades','condition'),true); + $mform->setHelpButton('conditiongradegroup[0]', array('gradecondition', get_string('help_gradecondition', 'condition'), 'condition')); + + // Conditions based on completion + if (completion_is_enabled($COURSE)) { + $completionoptions=array(); + $modinfo=get_fast_modinfo($COURSE); + foreach($modinfo->cms as $id=>$cm) { + $completionoptions[$id]=$cm->name; + } + asort($completionoptions); + $completionoptions=array(0=>get_string('none','condition'))+$completionoptions; + + $completionvalues=array( + COMPLETION_COMPLETE=>get_string('completion_complete','condition'), + COMPLETION_INCOMPLETE=>get_string('completion_incomplete','condition'), + COMPLETION_COMPLETE_PASS=>get_string('completion_pass','condition'), + COMPLETION_COMPLETE_FAIL=>get_string('completion_fail','condition')); + + $grouparray=array(); + $grouparray[] =& $mform->createElement('select','conditionsourcecmid','',$completionoptions); + $grouparray[] =& $mform->createElement('select','conditionrequiredcompletion','',$completionvalues); + $group = $mform->createElement('group','conditioncompletiongroup', + get_string('completioncondition', 'condition'),$grouparray); + + $count=empty($this->_cm) ? 1 : count($this->_cm->conditionscompletion)+1; + $this->repeat_elements(array($group),$count,array(), + 'conditioncompletionrepeats','conditioncompletionadds',2, + get_string('addcompletions','condition'),true); + $mform->setHelpButton('conditioncompletiongroup[0]', array('completioncondition', get_string('help_completioncondition', 'condition'), 'condition')); + } + + // Do we display availability info to students? + $mform->addElement('select', 'showavailability', get_string('showavailability', 'condition'), + array(CONDITION_STUDENTVIEW_SHOW=>get_string('showavailability_show', 'condition'), + CONDITION_STUDENTVIEW_HIDE=>get_string('showavailability_hide', 'condition'))); + $mform->setDefault('showavailability', CONDITION_STUDENTVIEW_SHOW); + $mform->setHelpButton('showavailability', array('showavailability', get_string('help_showavailability', 'condition'), 'condition')); + } + // Conditional activities: completion tracking section - require_once($CFG->libdir.'/completionlib.php'); if(completion_is_enabled($COURSE)) { $mform->addElement('header', '', get_string('activitycompletion', 'completion')); @@ -578,20 +687,7 @@ $cm=$this->_cm; global $COURSE; - $day=24*60*60; - $livedate=0; - if(isset($cm) && !is_null($cm->livedate)) { - $sign=$cm->livedate>=0 ? '+' : ''; // Already has - - $livedate=strtotime($sign.$cm->livedate.' days',$COURSE->startdate); - } - $removedate=0; - if(isset($cm) && !is_null($cm->removedate)) { - $sign=$cm->removedate>=0 ? '+' : ''; // Already has - - $removedate=strtotime($sign.$cm->removedate.' days',$COURSE->startdate); - } $new=array( - 'livedate'=> $livedate, - 'removedate'=> $removedate, 'stealth'=>isset($cm) ? $cm->stealth : 0, 'parentcmid'=>isset($cm) ? $cm->parentcmid : 0, 'showto'=>isset($cm) ? $cm->showto : '' Index: course/modedit.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/course/modedit.php,v retrieving revision 1.35 diff -u -r1.35 modedit.php --- course/modedit.php 2 Dec 2008 11:17:48 -0000 1.35 +++ course/modedit.php 18 Dec 2008 17:42:49 -0000 @@ -5,6 +5,9 @@ require_once("../config.php"); require_once("lib.php"); require_once($CFG->libdir.'/gradelib.php'); +// ou-specific begins (until 2.0) + require_once($CFG->libdir.'/conditionlib.php'); +// ou-specific ends (until 2.0) // ou-specific begins /** @@ -30,27 +33,8 @@ error("The repeated activity {$fromform->original} doesn't exist"); } set_field('course_modules','showto',$cmod->showto,'id',$fromform->coursemodule); - set_field('course_modules','livedate',$cmod->livedate,'id',$fromform->coursemodule); - set_field('course_modules','removedate',$cmod->removedate,'id',$fromform->coursemodule); } else { - // Set up the module's specified showto, livedate, removedate - $day=24*60*60; - if (isset($fromform->livedate)) { - if(!$fromform->livedate) { - $livedate='NULL'; - } else { - $livedate=round(($fromform->livedate-$course->startdate)/$day); - } - execute_sql("UPDATE {$CFG->prefix}course_modules SET livedate=$livedate WHERE id={$fromform->coursemodule}",false); - } - if (isset($fromform->removedate)) { - if(!$fromform->removedate) { - $removedate='NULL'; - } else { - $removedate=round(($fromform->removedate-$course->startdate)/$day); - } - execute_sql("UPDATE {$CFG->prefix}course_modules SET removedate=$removedate WHERE id={$fromform->coursemodule}",false); - } + // Set up the module's specified showto if(isset($fromform->showto)) { if(!$fromform->showto) { $showto='NULL'; @@ -65,18 +49,6 @@ if(isset($showto)) { $values.='showto='.$showto; } - if(isset($livedate)) { - if($values) { - $values.=','; - } - $values.='livedate='.$livedate; - } - if(isset($removedate)) { - if($values) { - $values.=','; - } - $values.='removedate='.$removedate; - } if($values && !execute_sql(" UPDATE @@ -99,15 +71,6 @@ global $COURSE; $form->stealth = $cm->stealth; $form->parentcmid = $cm->parentcmid; - $day=24*60*60; - if (!is_null($cm->livedate)) { - $sign = $cm->livedate>=0 ? '+' : ''; // Already has - - $form->livedate=strtotime($sign.$cm->livedate.' days',$COURSE->startdate); - } - if (!is_null($cm->removedate)) { - $sign = $cm->removedate>=0 ? '+' : ''; // Already has - - $form->removedate=strtotime($sign.$cm->removedate.' days',$COURSE->startdate); - } $form->showto = $cm->showto; } // ou-specific ends @@ -286,6 +249,11 @@ $form->completionview = $cm->completionview; $form->completionexpected=$cm->completionexpected; $form->completionusegrade = is_null($cm->completiongradeitemnumber)?0:1; + if(!empty($CFG->enableavailability)) { + $form->availablefrom = $cm->availablefrom; + $form->availableuntil = $cm->availableuntil; + $form->showavailability = $cm->showavailability; + } // ou-specific ends (until 2.0) // ou-specific begins @@ -473,13 +441,25 @@ set_coursemodule_completiongradeitemnumber( $fromform->coursemodule,$fromform->completiongradeitemnumber); } + + // Set up conditions + if($CFG->enableavailability) { + condition_info::update_cm_from_form( + (object)array('id'=>$fromform->coursemodule),$fromform,false); + } + $stuff=(object)array( + 'id'=>$fromform->coursemodule, + 'showavailability'=>$fromform->showavailability, + 'availablefrom'=>$fromform->availablefrom, + 'availableuntil'=>$fromform->availableuntil); + update_record('course_modules',$stuff); // ou-specific ends (until 2.0) if (isset($fromform->cmidnumber)) { //label // set cm idnumber set_coursemodule_idnumber($fromform->coursemodule, $fromform->cmidnumber); } - + add_to_log($course->id, "course", "update mod", "../mod/$fromform->modulename/view.php?id=$fromform->coursemodule", "$fromform->modulename $fromform->instance"); @@ -508,8 +488,7 @@ $fromform->instance = $returnfromfunc; // course_modules and course_sections each contain a reference - // to each other, so we have to update one of them twice. - + // to each other, so we have to update one of them twice. if (! $fromform->coursemodule = add_course_module($fromform) ) { error("Could not add a new course module"); } @@ -531,7 +510,14 @@ // ou-specific begins set_ou_fields($fromform,$course); // ou-specific ends - +// ou-specific begins (until 2.0) + // Set up conditions + if($CFG->enableavailability) { + condition_info::update_cm_from_form( + (object)array('id'=>$fromform->coursemodule),$fromform,false); + } +// ou-specific ends (until 2.0) + add_to_log($course->id, "course", "add mod", "../mod/$fromform->modulename/view.php?id=$fromform->coursemodule", "$fromform->modulename $fromform->instance"); Index: course/mod.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/course/mod.php,v retrieving revision 1.31 diff -u -r1.31 mod.php --- course/mod.php 11 Dec 2008 12:45:19 -0000 1.31 +++ course/mod.php 18 Dec 2008 17:42:49 -0000 @@ -8,30 +8,12 @@ // ou-specific begins require_once("../local/utils.php"); function ou_fix_coursemodules_data($mod,$adding) { - if(isset($mod->livedateenable)) { - $mod->livedate= - round((make_timestamp($mod->livedateyear, $mod->livedatemonth, $mod->livedateday)- - $mod->coursestartdate) / (24*60*60)); - } else { - $mod->livedate=null; - } - - if(isset($mod->removedateenable)) { - $mod->removedate= - round((make_timestamp($mod->removedateyear, $mod->removedatemonth, $mod->removedateday)- - $mod->coursestartdate) / (24*60*60)); - } else { - $mod->removedate=null; - } - if(empty($mod->stealth)) { $mod->stealth=null; } $course_module = new StdClass; $course_module->id = $mod->coursemodule; - $course_module->livedate = $mod->livedate; - $course_module->removedate = $mod->removedate; $course_module->stealth = isset($mod->stealth) ? $mod->stealth : null; $course_module->showto = isset($mod->showto) ? $mod->showto : null; @@ -395,6 +377,10 @@ if (!set_field("course_modules", "indent", $cm->indent, "id", $cm->id)) { error("Could not update the indent level on that course module"); } + +// ou-specific begins (until 2.0) + rebuild_course_cache($cm->course); +// ou-specific ends (until 2.0) if (SITEID == $cm->course) { redirect($CFG->wwwroot); Index: course/lib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/course/lib.php,v retrieving revision 1.197 diff -u -r1.197 lib.php --- course/lib.php 16 Dec 2008 10:22:06 -0000 1.197 +++ course/lib.php 18 Dec 2008 17:42:49 -0000 @@ -1182,7 +1182,12 @@ // ou-specific ends global $CFG; - +// ou-specific begins (until 2.0) + if(!empty($CFG->enableavailability)) { + require_once($CFG->libdir.'/conditionlib.php'); + } +// ou-specific ends (until 2.0) + $mod = array(); if (!$rawmods = get_course_mods($courseid)) { @@ -1205,7 +1210,21 @@ $mod[$seq]->groupmode = $rawmods[$seq]->groupmode; $mod[$seq]->groupingid = $rawmods[$seq]->groupingid; $mod[$seq]->groupmembersonly = $rawmods[$seq]->groupmembersonly; +// ou-specific begins (until 2.0) + $mod[$seq]->indent = $rawmods[$seq]->indent; + $mod[$seq]->completion = $rawmods[$seq]->completion; +// ou-specific ends (until 2.0) $mod[$seq]->extra = ""; +// ou-specific begins (until 2.0) + if(!empty($CFG->enableavailability)) { + condition_info::fill_availability_conditions($rawmods[$seq]); + $mod[$seq]->availablefrom = $rawmods[$seq]->availablefrom; + $mod[$seq]->availableuntil = $rawmods[$seq]->availableuntil; + $mod[$seq]->showavailability = $rawmods[$seq]->showavailability; + $mod[$seq]->conditionscompletion = $rawmods[$seq]->conditionscompletion; + $mod[$seq]->conditionsgrade = $rawmods[$seq]->conditionsgrade; + } +// ou-specific ends (until 2.0) $modname = $mod[$seq]->mod; $functionname = $modname."_get_coursemodule_info"; @@ -1260,7 +1279,12 @@ */ function &get_fast_modinfo(&$course, $userid=0) { global $CFG, $USER; - +// ou-specific begins (until 2.0) + if(!empty($CFG->enableavailability)) { + require_once($CFG->libdir.'/conditionlib.php'); + } +// ou-specific ends (until 2.0) + // ou-specific begins /// If using shared activities course, change the 'course' name require_once($CFG->dirroot.'/course/format/sharedactv/sharedactv.php'); @@ -1341,10 +1365,10 @@ preload_course_contexts($course->id); // ou-specific begins - // Require livedate, removedate, showto and stealth + // Require showto and stealth // Could get everything in 1 query if name given to module in cm (or not required) // use get_records_sql() as more performant - $sql = "SELECT id, livedate, removedate, showto, stealth FROM {$CFG->prefix}course_modules WHERE course = {$course->id}"; + $sql = "SELECT id, showto, stealth FROM {$CFG->prefix}course_modules WHERE course = {$course->id}"; if (($oufields = get_records_sql($sql)) === false) { $oufields = array(); } @@ -1367,9 +1391,31 @@ $cm->groupmode = $mod->groupmode; $cm->groupingid = $mod->groupingid; $cm->groupmembersonly = $mod->groupmembersonly; +// ou-specific begins (until 2.0) + $cm->indent = $mod->indent; + $cm->completion = $mod->completion; +// ou-specific ends (until 2.0) $cm->extra = isset($mod->extra) ? urldecode($mod->extra) : ''; $cm->icon = isset($mod->icon) ? $mod->icon : ''; $cm->uservisible = true; +// ou-specific begins (until 2.0) + if(!empty($CFG->enableavailability)) { + // We must have completion information from modinfo. If it's not + // there, cache needs rebuilding + if(!isset($mod->availablefrom)) { + debugging('enableavailability option was changed; rebuilding '. + 'cache for course '.$course->id); + rebuild_course_cache($course->id,true); + // Re-enter this routine to do it all properly + return get_fast_modinfo($course,$userid); + } + $cm->availablefrom = $mod->availablefrom; + $cm->availableuntil = $mod->availableuntil; + $cm->showavailability = $mod->showavailability; + $cm->conditionscompletion = $mod->conditionscompletion; + $cm->conditionsgrade = $mod->conditionsgrade; + } +// ou-specific ends (until 2.0) // ou-specific begins $cm->extraclass = isset($mod->extraclass) ? $mod->extraclass : ''; if(isset($mod->filepath)) { @@ -1381,8 +1427,6 @@ } if (isset($oufields[$cm->id])) { $oucm = $oufields[$cm->id]; - $cm->livedate = $oucm->livedate; - $cm->removedate = $oucm->removedate; $cm->showto = $oucm->showto; $cm->stealth = $oucm->stealth; } @@ -1399,8 +1443,34 @@ $modcontext = get_context_instance(CONTEXT_MODULE,$cm->id); - if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', - $modcontext, $userid)) { +// ou-specific begins (until 2.0) + if(!empty($CFG->enableavailability)) { + // Unfortunately the next call really wants to call + // get_fast_modinfo, but that would be recursive, so we fake up a + // modinfo for it already + if(empty($minimalmodinfo)) { + $minimalmodinfo=new stdClass(); + $minimalmodinfo->cms=array(); + foreach($info as $mod) { + $minimalcm=new stdClass(); + $minimalcm->id=$mod->cm; + $minimalcm->name=urldecode($mod->name); + $minimalmodinfo->cms[$minimalcm->id]=$minimalcm; + } + } + + // Get availability information + $ci = new condition_info($cm); + $cm->available=$ci->is_available($cm->availableinfo,true,$userid, + $minimalmodinfo); + } else { + $cm->available=true; + } + $modcontext = get_context_instance(CONTEXT_MODULE,$cm->id); + if ((!$cm->visible or !$cm->available) and !has_capability('moodle/course:viewhiddenactivities', $modcontext, $userid)) { +// This last line used to be: +// if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', $contexts[$cm->id], $userid)) { +// ou-specific begins (until 2.0) $cm->uservisible = false; } else if (!empty($CFG->enablegroupings) and !empty($cm->groupmembersonly) @@ -1467,8 +1537,14 @@ error("No modules are installed!"); } - if ($rawmods = get_course_mods($courseid)) { - foreach($rawmods as $mod) { // Index the mods +// ou-specific begins (until 2.0) + global $COURSE; + $course = ($courseid==$COURSE->id) ? $COURSE : get_record('course','id',$courseid); + $modinfo = get_fast_modinfo($course); + + if ($rawmods=$modinfo->cms) { +// ou-specific ends (until 2.0) + foreach($rawmods as $mod) { // Index the mods if (empty($modnames[$mod->modname])) { continue; } @@ -1607,7 +1683,10 @@ } if (isset($modinfo->cms[$modnumber])) { - if (!$modinfo->cms[$modnumber]->uservisible) { +// ou-specific begins (until 2.0) + if (!$modinfo->cms[$modnumber]->uservisible && + empty($modinfo->cms[$modnumber]->showavailability)) { +// ou-specific ends (until 2.0) // visibility shortcut continue; } @@ -1616,7 +1695,10 @@ // module not installed continue; } - if (!coursemodule_visible_for_user($mod)) { +// ou-specific begins (until 2.0) + if (!coursemodule_visible_for_user($mod) && + empty($mod->showavailability)) { +// ou-specific ends (until 2.0) // full visibility check continue; } @@ -1652,7 +1734,10 @@ } if ($mod->modname == "label") { - if (!$mod->visible) { +// ou-specific begins (until 2.0) +// if (!$mod->visible) { + if (!$mod->visible || !$mod->uservisible) { +// ou-specific ends (until 2.0) echo "
"; } echo format_text($extra, FORMAT_HTML, $labelformatoptions); @@ -1707,8 +1792,14 @@ $altname = get_accesshide(' '.$altname); } - $linkcss = $mod->visible ? "" : " class=\"dimmed\" "; - echo 'uservisible) { + // Display normal module link +// ou-specific ends (until 2.0) + $linkcss = $mod->visible ? "" : " class=\"dimmed\" "; + echo ''. @@ -1730,12 +1821,20 @@ } // ou-specific ends - if (!empty($CFG->enablegroupings) && !empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { - if (!isset($groupings)) { - $groupings = groups_get_all_groupings($course->id); + if (!empty($CFG->enablegroupings) && !empty($mod->groupingid) && has_capability('moodle/course:managegroups', get_context_instance(CONTEXT_COURSE, $course->id))) { + if (!isset($groupings)) { + $groupings = groups_get_all_groupings($course->id); + } + echo " (".format_string($groupings[$mod->groupingid]->name).')'; } - echo " (".format_string($groupings[$mod->groupingid]->name).')'; +// ou-specific begins (until 2.0) + } else { + // Display greyed-out text of link + echo ''. + ' '. + $instancename.$altname.''; } +// ou-specific ends (until 2.0) } if ($usetracking && $mod->modname == 'forum') { if ($unread = forum_tp_count_forum_unread_posts($mod, $course)) { @@ -1793,7 +1892,8 @@ $completion=$hidecompletion ? COMPLETION_TRACKING_NONE : completion_is_enabled($course,$mod); - if($completion!=COMPLETION_TRACKING_NONE && isloggedin() && !isguestuser()) { + if($completion!=COMPLETION_TRACKING_NONE && isloggedin() && + !isguestuser() && $mod->uservisible) { $completiondata=completion_get_data($course,$mod,true); $completionicon=''; if($isediting) { @@ -1858,6 +1958,21 @@ } } catch (Exception $e) { debugging('An exception occurred while retrieving completion information: '.$e->getMessage()); + } + + // Show availability information (for someone who isn't allowed to + // see the activity itself, or for staff) + if(!$mod->uservisible) { + echo '
'.$mod->availableinfo.'
'; + } else if($isediting && !empty($CFG->enableavailability)) { + $ci = new condition_info($mod); + $fullinfo=$ci->get_full_information(); + if($fullinfo) { + echo '
'.get_string($mod->showavailability + ? 'userrestriction_visible' + : 'userrestriction_hidden','condition', + $fullinfo).'
'; + } } // ou-specific ends (until 2.0) Index: local/version.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/local/version.php,v retrieving revision 1.67 diff -u -r1.67 version.php --- local/version.php 2 Dec 2008 11:17:49 -0000 1.67 +++ local/version.php 18 Dec 2008 17:42:49 -0000 @@ -9,5 +9,5 @@ */ /** The version stamp for the local DB modifications. */ -$local_version = 2008112800; +$local_version = 2008121801; ?> Index: local/module_access.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/local/module_access.php,v retrieving revision 1.13 diff -u -r1.13 module_access.php --- local/module_access.php 21 Jul 2008 12:02:46 -0000 1.13 +++ local/module_access.php 18 Dec 2008 17:42:49 -0000 @@ -164,30 +164,6 @@ } // endif - $dateformat='j M Y'; // Kind of should be a constant but well - if(!is_null($cm->livedate)) { - // Only displays if it's after livedate days from start of course - $sign=$cm->livedate>=0 ? '+' : ''; // Already has - - $livetime=strtotime($sign.$cm->livedate.' days',$course->startdate); - $information.='Not accessible until '.date($dateformat,$livetime).'. '; - if(time() < $livetime) { - if (!$bviewhiddenactivities) { - $accessible=false; - } - $visible=false; - } - } - if(!is_null($cm->removedate)) { - $sign=$cm->removedate>=0 ? '+' : ''; // Already has - - $removetime=strtotime($sign.$cm->removedate.' days',$course->startdate); - $information.='Not accessible on or after '.date($dateformat,$removetime).'. '; - if(time() >= $removetime) { - if (!$bviewhiddenactivities) { - $accessible=false; - } - $visible=false; - } - } if($cm->showto) { global $CFG; // Requires OU SAMS support Index: mod/quiz/report/paramcheck/report.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/mod/quiz/report/paramcheck/report.php,v retrieving revision 1.6 diff -u -r1.6 report.php --- mod/quiz/report/paramcheck/report.php 3 Dec 2008 08:42:13 -0000 1.6 +++ mod/quiz/report/paramcheck/report.php 18 Dec 2008 17:42:49 -0000 @@ -568,12 +568,12 @@ * livedate = Available from � if stealthed is on this must be the open date * removedate= Unavailable from � if stealthed is on this must be the close date plus 1 day */ - if($cmo->livedate){ + if($cmo->availablefrom){ $rowdata[0] = "Available From"; - $cmolivedate = userdate(($cmo->livedate * (24*60*60)) +($course->startdate)); + $cmolivedate = userdate($cmo->availablefrom); $coursestartdate = userdate($course->startdate); $opentime = userdate($quiz->timeopen); - if (!($quiz->timeopen < ($cmo->livedate * (24*60*60)) +($course->startdate))){ + if (!($quiz->timeopen < $cmo->availablefrom)){ $rowdata[1] = $cmolivedate; $rowdata[2] = "Nothing to Display"; } else{ @@ -598,13 +598,13 @@ * livedate = Available from � if stealthed is on this must be the open date * removedate= Unavailable from � if stealthed is on this must be the close date plus 1 day */ - if($cmo->removedate >0){ + if($cmo->availableuntil){ $rowdata[0] = "Unavailable From"; - $cmoremovedate = userdate(($cmo->removedate * (24*60*60)) +($course->startdate)); + $cmoremovedate = userdate($cmo->availableuntil); $coursestartdate = userdate($course->startdate); $timeclose = userdate($quiz->timeclose); - $remove = ($cmo->removedate) * (24*60*60) + ($course->startdate); - $removeplus1 = ($cmo->removedate +1) * (24*60*60) + ($course->startdate); + $remove = $cmo->availableuntil; + $removeplus1 = strtotime('+1 day',$remove); if (($quiz->timeclose < $remove) OR ($removeplus1 > $quiz->timeclose)){ $rowdata[1] = "$cmoremovedate"; $rowdata[2] = "$timeclose"; Index: backup/restorelib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/backup/restorelib.php,v retrieving revision 1.88 diff -u -r1.88 restorelib.php --- backup/restorelib.php 11 Dec 2008 15:32:58 -0000 1.88 +++ backup/restorelib.php 18 Dec 2008 17:42:49 -0000 @@ -1184,8 +1184,6 @@ $course_module->indent = $mod->indent; $course_module->visible = $mod->visible; // ou-specific begins - $course_module->livedate = $mod->livedate; - $course_module->removedate = $mod->removedate; $course_module->showto = $mod->showto; $course_module->stealth = $mod->stealth; if (isset($mod->parentcmid)) { @@ -1216,6 +1214,10 @@ $course_module->completiongradeitemnumber=$mod->completiongradeitemnumber; $course_module->completionview=$mod->completionview; $course_module->completionexpected=$mod->completionexpected; + + $course_module->availablefrom=$mod->availablefrom+$restore->course_startdateoffset; + $course_module->availableuntil=$mod->availableuntil+$restore->course_startdateoffset; + $course_module->showavailability=$mod->showavailability; // ou-specific ends (until 2.0) $newidmod = insert_record("course_modules", addslashes_recursive($course_module)); @@ -1315,6 +1317,62 @@ } } } + + // Store availability information + if($status && !empty($info->availabilitydata) && count($info->availabilitydata)>0) { + + foreach($info->availabilitydata as $data) { + // Convert cmid + $newcmid=backup_getid($restore->backup_unique_code, 'course_modules', $data->coursemoduleid); + if($newcmid) { + $data->coursemoduleid=$newcmid->new_id; + } else { + if (!defined('RESTORE_SILENTLY')) { + echo "

Can't find new ID for cm $data->coursemoduleid, ignoring availability condition.

"; + } + $status=false; + continue; + } + + // Convert source cmid + if($data->sourcecmid) { + $newcmid=backup_getid($restore->backup_unique_code, 'course_modules', $data->sourcecmid); + if($newcmid) { + $data->sourcecmid=$newcmid->new_id; + } else { + if (!defined('RESTORE_SILENTLY')) { + echo "

Can't find new ID for source cm $data->sourcecmid, ignoring availability condition.

"; + } + $status=false; + continue; + } + } + + // Convert grade id + if($data->gradeitemid) { + $newgradeid=backup_getid($restore->backup_unique_code, + 'grade_items',$data->gradeitemid); + if($newgradeid) { + $data->gradeitemid=$newgradeid->new_id; + } else { + if (!defined('RESTORE_SILENTLY')) { + echo "

Can't find new ID for grade item $data->gradeitemid, ignoring availability condition.

"; + } + $status=false; + continue; + } + } + + // Add record + if(!insert_record('course_modules_availability',$data)) { + if (!defined('RESTORE_SILENTLY')) { + echo "

Failed to insert availability data record.

"; + } + $status=false; + continue; + } + } + } // ou-specific ends (until 2.0) // ou-specific begins @@ -6075,14 +6133,15 @@ isset($this->info->tempmod->completionview) ? $this->info->tempmod->completionview : 0; $this->info->tempsection->mods[$this->info->tempmod->id]->completionexpected = isset($this->info->tempmod->completionexpected) ? $this->info->tempmod->completionexpected : 0; + $this->info->tempsection->mods[$this->info->tempmod->id]->availablefrom = + isset($this->info->tempmod->availablefrom) ? $this->info->tempmod->availablefrom : 0; + $this->info->tempsection->mods[$this->info->tempmod->id]->availableuntil = + isset($this->info->tempmod->availableuntil) ? $this->info->tempmod->availableuntil : 0; + $this->info->tempsection->mods[$this->info->tempmod->id]->showavailability = + isset($this->info->tempmod->showavailability) ? $this->info->tempmod->showavailability : 0; // ou-specific ends (until 2.0) // ou-specific begins - // isset test added for backwards compatability with old backups - $this->info->tempsection->mods[$this->info->tempmod->id]->livedate = - isset($this->info->tempmod->livedate) ? $this->info->tempmod->livedate : NULL; - $this->info->tempsection->mods[$this->info->tempmod->id]->removedate = - isset($this->info->tempmod->removedate) ? $this->info->tempmod->removedate : NULL; $this->info->tempsection->mods[$this->info->tempmod->id]->showto = isset($this->info->tempmod->showto) ? $this->info->tempmod->showto : NULL; $this->info->tempsection->mods[$this->info->tempmod->id]->stealth = @@ -6141,6 +6200,15 @@ case "COMPLETIONEXPECTED": $this->info->tempmod->completionexpected = $this->getContents(); break; + case "AVAILABLEFROM": + $this->info->tempmod->availablefrom = $this->getContents(); + break; + case "AVAILABLEUNTIL": + $this->info->tempmod->availableuntil = $this->getContents(); + break; + case "SHOWAVAILABILITY": + $this->info->tempmod->showavailability = $this->getContents(); + break; // ou-specific ends (until 2.0) // ou-specific begins // NOTE: This code is horrifically confusing! For some inane reason, they chose @@ -6149,10 +6217,16 @@ // So this code runs when it encounters the inner tags that actually define the // given contents. Then we move on to the second part (level 6) above. case "LIVEDATE": - $this->info->tempmod->livedate = self::int_allow_nulls($this->getContents()); + if(!is_null(self::int_allow_nulls($this->getContents()))) { + // Fail! + print "

Error! cm {$this->info->tempmod->id} ({$this->info->tempmod->type}) has livedate set, cannot restore from old backup

."; + } break; case "REMOVEDATE": - $this->info->tempmod->removedate = self::int_allow_nulls($this->getContents()); + if(!is_null(self::int_allow_nulls($this->getContents()))) { + // Fail! + print "

Error! cm {$this->info->tempmod->id} ({$this->info->tempmod->type}) has removedate set, cannot restore from old backup

."; + } break; case "SHOWTO": $this->info->tempmod->showto = self::string_allow_nulls($this->getContents()); @@ -6286,6 +6360,40 @@ break; case 'TIMEMODIFIED' : $this->info->tempcompletion->timemodified=$this->getContents(); + break; + } + } + } + + if (isset($this->tree[7]) && $this->tree[7] == "AVAILABILITYDATA") { + if($this->level == 8) { + switch($tagName) { + case 'AVAILABILITY': + // Got all data to make completion entry... + $this->info->tempavailability->coursemoduleid=$this->info->tempmod->id; + $this->info->availabilitydata[]=$this->info->tempavailability; + unset($this->info->tempavailability); + $this->info->tempavailability=new stdClass; + break; + } + } + + if($this->level == 9) { + switch($tagName) { + case 'SOURCECMID' : + $this->info->tempavailability->sourcecmid=$this->getContents(); + break; + case 'REQUIREDCOMPLETION' : + $this->info->tempavailability->requiredcompletion=$this->getContents(); + break; + case 'GRADEITEMID' : + $this->info->tempavailability->gradeitemid=$this->getContents(); + break; + case 'GRADEMIN' : + $this->info->tempavailability->grademin=$this->getContents(); + break; + case 'GRADEMAX' : + $this->info->tempavailability->grademax=$this->getContents(); break; } } Index: backup/backuplib.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/backup/backuplib.php,v retrieving revision 1.57 diff -u -r1.57 backuplib.php --- backup/backuplib.php 11 Dec 2008 14:39:00 -0000 1.57 +++ backup/backuplib.php 18 Dec 2008 17:42:48 -0000 @@ -1364,10 +1364,11 @@ fwrite ($bf,full_tag("COMPLETIONGRADEITEMNUMBER",6,false,$course_module->completiongradeitemnumber)); fwrite ($bf,full_tag("COMPLETIONVIEW",6,false,$course_module->completionview)); fwrite ($bf,full_tag("COMPLETIONEXPECTED",6,false,$course_module->completionexpected)); + fwrite ($bf,full_tag("AVAILABLEFROM",6,false,$course_module->availablefrom)); + fwrite ($bf,full_tag("AVAILABLEUNTIL",6,false,$course_module->availableuntil)); + fwrite ($bf,full_tag("SHOWAVAILABILITY",6,false,$course_module->showavailability)); // ou-specific ends (until 2.0) // ou-specific begins - fwrite ($bf,full_tag("LIVEDATE",6,false,$course_module->livedate)); - fwrite ($bf,full_tag("REMOVEDATE",6,false,$course_module->removedate)); fwrite ($bf,full_tag("SHOWTO",6,false,$course_module->showto)); fwrite ($bf,full_tag("STEALTH",6,false,$course_module->stealth)); fwrite ($bf,full_tag("PARENTCMID",6,false,$course_module->parentcmid)); @@ -1405,6 +1406,26 @@ } fwrite ($bf,end_tag("COMPLETIONDATA",6,true)); + } + // Write availability data if enabled + require_once($CFG->libdir.'/conditionlib.php'); + if(!empty($CFG->enableavailability)) { + fwrite ($bf,start_tag("AVAILABILITYDATA",6,true)); + // Get all availability restrictions for this activity + $data=get_records('course_modules_availability', + 'coursemoduleid',$course_module->id); + $data=$data ? $data : array(); + foreach($data as $availability) { + // Write availability record + fwrite ($bf,start_tag("AVAILABILITY",7,true)); + fwrite ($bf,full_tag("SOURCECMID",8,false,$availability->sourcecmid)); + fwrite ($bf,full_tag("REQUIREDCOMPLETION",8,false,$availability->requiredcompletion)); + fwrite ($bf,full_tag("GRADEITEMID",8,false,$availability->gradeitemid)); + fwrite ($bf,full_tag("GRADEMIN",8,false,$availability->grademin)); + fwrite ($bf,full_tag("GRADEMAX",8,false,$availability->grademax)); + fwrite ($bf,end_tag("AVAILABILITY",7,true)); + } + fwrite ($bf,end_tag("AVAILABILITYDATA",6,true)); } // ou-specific ends (until 2.0) Index: lib/grade/grade_grade.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/lib/grade/grade_grade.php,v retrieving revision 1.9 diff -u -r1.9 grade_grade.php --- lib/grade/grade_grade.php 7 Aug 2008 11:28:09 -0000 1.9 +++ lib/grade/grade_grade.php 18 Dec 2008 17:42:49 -0000 @@ -728,6 +728,12 @@ * @param bool deleted True if grade was actually deleted */ function notify_changed($deleted) { + // Grades may be cached in user session + global $USER,$SESSION; + if($USER->id==$this->userid) { + unset($SESSION->gradescorecache[$this->itemid]); + } + // Ignore during restore // TODO There should be a proper way to determine when we are in restore // so that this hack looking for a $restore global is not needed. Index: local/db/upgrade.php =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/local/db/upgrade.php,v retrieving revision 1.71 diff -u -r1.71 upgrade.php --- local/db/upgrade.php 17 Dec 2008 12:01:36 -0000 1.71 +++ local/db/upgrade.php 18 Dec 2008 17:42:49 -0000 @@ -78,6 +78,7 @@ $success = $success && update_resource_file_aliases($oldversion, $feedback); $success = $success && delete_activity_integration_table($oldversion, $feedback); $success = $success && match_oci_vle_dbs($oldversion, $feedback); + $success = $success && update_livedate_fields($oldversion, $feedback); return $success; } @@ -89,27 +90,12 @@ if ($success && $oldversion < 2006010900) { // Check if required course_modules table columns have been added $table = new XMLDBTable('course_modules'); - $field = new XMLDBField('livedate'); + $field = new XMLDBField('showto'); if (!field_exists($table, $field)) { $tw=new transaction_wrapper(); - // Define livedate field to be added to course_modules table - $field->setAttributes(XMLDB_TYPE_INTEGER, '5', null, null, null, null, null, null, 'groupmode'); - - // Add livedate field to course_modules table - $success &= add_field($table, $field); - - // Define removedate field to be added to course_modules table - $field = new XMLDBField('removedate'); - $field->setAttributes(XMLDB_TYPE_INTEGER, '5', null, null, null, null, null, null, 'livedate'); - - // Add removedate field to course_modules table - $success &= add_field($table, $field); - - // Define removedate field to be added to course_modules table - $field = new XMLDBField('showto'); - $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null, 'removedate'); - - // Add removedate field to course_modules table + + $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null, 'groupmode'); + // Add showto field to course_modules table $success &= add_field($table, $field); $tw->complete($success); @@ -1718,6 +1704,133 @@ $tw->complete($success); } return $success; +} + +function update_livedate_fields($oldversion, $feedback) { + $success = true; + global $db,$CFG; + + if ($success && $oldversion < 2008121801) { + $tw=new transaction_wrapper(); + + print 'Yayyyyyyy'; + + /// Define field availablefrom to be added to course_modules + $table = new XMLDBTable('course_modules'); + $field = new XMLDBField('availablefrom'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'completionexpected'); + + /// Conditionally launch add field availablefrom + if (!field_exists($table, $field)) { + $success = $success && add_field($table, $field); + } + + /// Define field availableuntil to be added to course_modules + $field = new XMLDBField('availableuntil'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'availablefrom'); + + /// Conditionally launch add field availableuntil + if (!field_exists($table, $field)) { + $success = $success && add_field($table, $field); + } + + /// Define field showavailability to be added to course_modules + $field = new XMLDBField('showavailability'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'availableuntil'); + + /// Conditionally launch add field showavailability + if (!field_exists($table, $field)) { + $success = $success && add_field($table, $field); + } + + /// Define table course_modules_availability to be created + $table = new XMLDBTable('course_modules_availability'); + + /// Adding fields to table course_modules_availability + $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null); + $table->addFieldInfo('coursemoduleid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); + $table->addFieldInfo('sourcecmid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); + $table->addFieldInfo('requiredcompletion', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, null, null, null, null, null); + $table->addFieldInfo('gradeitemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null); + $table->addFieldInfo('grademin', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null, null, null); + $table->addFieldInfo('grademax', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null, null, null); + + /// Adding keys to table course_modules_availability + $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->addKeyInfo('coursemoduleid', XMLDB_KEY_FOREIGN, array('coursemoduleid'), 'course_modules', array('id')); + $table->addKeyInfo('sourcecmid', XMLDB_KEY_FOREIGN, array('sourcecmid'), 'course_modules', array('id')); + $table->addKeyInfo('gradeitemid', XMLDB_KEY_FOREIGN, array('gradeitemid'), 'grade_items', array('id')); + + /// Conditionally launch create table for course_modules_availability + if (!table_exists($table)) { + $success = $success && create_table($table); + } + + /// For developer upgrades, turn on the conditional activities and completion + /// features automatically (to gain more testing) + if(debugging('',DEBUG_DEVELOPER)) { + set_config('enableavailability',1); + set_config('enablecompletion',1); + } + + $table = new XMLDBTable('course_modules'); + $field = new XMLDBField('livedate'); + if(field_exists($table,$field)) { + // OK, we now have the new fields. But we need to set up the date fields + // based on the old livedate, removedate. + $success = $success && execute_sql(" +UPDATE + {$CFG->prefix}course_modules +SET + availablefrom= + ( + SELECT + EXTRACT(EPOCH FROM date_trunc('day',(TIMESTAMP WITH TIME ZONE 'epoch' + c.startdate *INTERVAL '1 second') + ({$CFG->prefix}course_modules.livedate || ' days')::interval)) + FROM + mdl_course c + WHERE c.id={$CFG->prefix}course_modules.course +) +WHERE + livedate IS NOT NULL"); + $success = $success && execute_sql(" +UPDATE + {$CFG->prefix}course_modules +SET + availableuntil= + ( + SELECT + EXTRACT(EPOCH FROM date_trunc('day',(TIMESTAMP WITH TIME ZONE 'epoch' + c.startdate *INTERVAL '1 second') + ({$CFG->prefix}course_modules.removedate || ' days')::interval)) + FROM + mdl_course c + WHERE c.id={$CFG->prefix}course_modules.course +) +WHERE + removedate IS NOT NULL"); + + // Before we drop the old fields, let's just save them to a file, 'kay? + $result="CM ID,livedate,removedate,availablefrom,availableuntil\n"; + $rs=get_recordset_select('course_modules','livedate IS NOT NULL OR removedate IS NOT NULL', + 'id','id,livedate,removedate,availablefrom,availableuntil'); + while($rec=rs_fetch_next_record($rs)) { + $result.="$rec->id,$rec->livedate,$rec->removedate,$rec->availablefrom,$rec->availableuntil\n"; + } + rs_close($rs); + file_put_contents($CFG->dataroot.'/1/livedateupgrade.csv',$result); + unset($result); + + // Yay, now drop the unwanted fields + $success = $success && drop_field($table,$field); + $field = new XMLDBField('removedate'); + $success = $success && drop_field($table,$field); + } + + /// Changes to modinfo mean we need to rebuild course cache + rebuild_course_cache(0,true); + + $tw->complete($success); + } + + return $success; } //function do_something($oldversion, $feedback) { Index: theme/standard/styles_fonts.css =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/theme/standard/styles_fonts.css,v retrieving revision 1.34 diff -u -r1.34 styles_fonts.css --- theme/standard/styles_fonts.css 14 Jul 2008 11:32:27 -0000 1.34 +++ theme/standard/styles_fonts.css 18 Dec 2008 17:42:49 -0000 @@ -578,6 +578,19 @@ color: #666666; } +#course-view .availabilityinfo { + font-size:0.85em; + color:#aaa; +} +#course-view .availabilityinfo strong { + font-weight:normal; + color:black; +} +#course-view .dimmed_text img { + opacity:0.3; + filter: alpha(opacity='30'); +} + /*** *** Doc ***/ Index: lib/db/install.xml =================================================================== RCS file: /home/cvs_repositories/globalcvs/ou-moodle/lib/db/install.xml,v retrieving revision 1.24 diff -u -r1.24 install.xml --- lib/db/install.xml 5 Nov 2008 09:26:54 -0000 1.24 +++ lib/db/install.xml 18 Dec 2008 17:42:49 -0000 @@ -139,7 +139,7 @@ - +
@@ -163,7 +163,10 @@ 2 = automatic tracking, system should mark completion according to rules specified in course_moduleS_completion" PREVIOUS="groupmembersonly" NEXT="completiongradeitemnumber"/> - + + + + @@ -179,7 +182,24 @@
- +
+ + + + + + + + + + + + + + + +
+ Index: lang/en_utf8_local/condition.php =================================================================== RCS file: lang/en_utf8_local/condition.php diff -N lang/en_utf8_local/condition.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8_local/condition.php 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,35 @@ +$a is incomplete.'; +$string['requires_completion_1']='Not available until the activity $a is marked complete.'; +$string['requires_completion_2']='Not available until the activity $a is complete and passed.'; +$string['requires_completion_3']='Not available unless the activity $a is complete and failed.'; +$string['requires_date']='Not available until $a.'; +$string['requires_date_before']='Not available from $a.'; +$string['requires_grade_any']='Not available until you have a grade in $a.'; +$string['requires_grade_min']='Not available until you achieve a required score in $a.'; +$string['requires_grade_max']='Not available unless you get an appropriate score in $a.'; +$string['requires_grade_range']='Not available unless you get a particular score in $a.'; +$string['showavailability']='Before activity is available'; +$string['showavailability_show']='Show activity greyed-out, with restriction information'; +$string['showavailability_hide']='Hide activity entirely'; +$string['userrestriction_visible']='Activity conditionally restricted: ‘$a’'; +$string['userrestriction_hidden']='Activity conditionally restricted (completely hidden, no message): ‘$a’'; +?> Index: lang/en_utf8_local/help/condition/gradecondition.html =================================================================== RCS file: lang/en_utf8_local/help/condition/gradecondition.html diff -N lang/en_utf8_local/help/condition/gradecondition.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8_local/help/condition/gradecondition.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +

Grade condition

+ +

+You can specify a condition on any grade in the course: the full course grade, +the grade for any activity, or a custom grade that you create manually. +

+ +

+You can enter either a minimum value (≥), a maximum value (<), both, or +neither. The activity will only appear if the student has a value for the +specified grade, and if it falls within any specified number range. +

+ +

+You can add more than one grade condition. All conditions must be met in order +for the activity to appear. +

+ +
    +
  • The range numbers can be fractional (with up to five decimal places) if + necessary.
  • +
  • Be careful with the maximum value; if the maximum is 7, a student who + scores exactly 7 will not see the activity. You could set it to 7.01 if + you really wanted to include 7.
  • +
  • If creating several different activities that appear according to grade + ranges, use the same number for the maximum of one activity, and the minimum + of the next. For example, you might create one activity with a maximum of 7 + and another with a minimum of 7. The first would appear to everyone scoring + between 0 and 6.99999, and the second would appear to everyone scoring 7.00000 + to 10. This guarantees that everyone with a grade will see one or other.
  • +
Index: lang/en_utf8_local/help/condition/conditiondates.html =================================================================== RCS file: lang/en_utf8_local/help/condition/conditiondates.html diff -N lang/en_utf8_local/help/condition/conditiondates.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8_local/help/condition/conditiondates.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,23 @@ +

Available dates

+ +

+Using the 'Only available from' and 'Only available until' dates, you can make +an activity appear or disappear. The activity is only shown to students from the +'available from' date, and it disappears on the 'available until' date. Students +cannot access it outside those times, even if they guess the URL. +

+ +

+By default both dates are disabled, meaning that the activity is available at +any time (as long as the student can access the course). +

+ +
    +
  • If you choose to show information about an activity that is unavailable, + then before the 'available from' date, students will see the activity + greyed-out, with informational text about the date that it appears.
  • +
  • The activity completely vanishes on the 'available to' date, even if + you've chosen to show information.
  • +
  • Setting 'Visible' to 'Hide' overrides these settings. If you set 'Visible' + to 'Hide', the activity is never available regardless of date.
  • +
Index: lang/en_utf8_local/help/condition/completioncondition.html =================================================================== RCS file: lang/en_utf8_local/help/condition/completioncondition.html diff -N lang/en_utf8_local/help/condition/completioncondition.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8_local/help/condition/completioncondition.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,20 @@ +

Activity completion condition

+ +

+You can set a condition based on whether the user has completed another +activity. +

+ +

+This feature uses the completion options that have been configured for the +other activity. You can choose whether the activity must be complete, +incomplete, complete and passed, or complete and failed. The final two +options only work if you use grade-based completion and set a pass mark on +the grade item. (Please look at the documentation for activity completion +if this is unclear.) +

+ +

+You can add more than one completion condition. All conditions must be met in +order for the activity to appear. +

Index: lang/en_utf8_local/help/condition/showavailability.html =================================================================== RCS file: lang/en_utf8_local/help/condition/showavailability.html diff -N lang/en_utf8_local/help/condition/showavailability.html --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lang/en_utf8_local/help/condition/showavailability.html 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,27 @@ +

Unavailable activity display

+ +

+When an activity is unavailable due to the restrictions in this box, there are +two possibilities: +

+ +
    +
  1. The activity displays to users, but as greyed-out text instead of a link. + Informational text below the activity indicates when, or under what + conditions, it will become available.
  2. +
  3. The activity does not display to users at all.
  4. +
+ +

+In both cases, once the activity becomes available, it displays as normal. +

+ +
    +
  • Users with the 'view hidden activities' capability can still see + unavailable activities, regardless of this setting. The informational text + always appears to them.
  • +
  • This option does not affect the standard 'visibility' option (also controlled + by the eye icon). You can still use this icon to quickly and completely hide + any activity from students, for example if you find a problem with the + activity.
  • +
Index: lib/conditionlib.php =================================================================== RCS file: lib/conditionlib.php diff -N lib/conditionlib.php --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/conditionlib.php 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,534 @@ +conditionsgrade, ->conditionscompletion which should come from + * get_fast_modinfo. Should have ->availablefrom, ->availableuntil, + * and ->showavailability, ->course; but the only required thing is ->id. + * @param int $expectingmissing Used to control whether or not a developer + * debugging message (performance warning) will be displayed if some of + * the above data is missing and needs to be retrieved; a + * CONDITION_MISSING_xx constant + * @param bool $loaddata If you need a 'write-only' object, set this value + * to false to prevent database access from constructor + * @return condition_info Object which can retrieve information about the + * activity + */ + public function __construct($cm,$expectingmissing=CONDITION_MISSING_NOTHING, + $loaddata=true) { + + // Check ID as otherwise we can't do the other queries + if(empty($cm->id)) { + throw new coding_exception("Invalid parameters; course-module ID not included"); + } + + // If not loading data, don't do anything else + if(!$loaddata) { + $this->cm=(object)array('id'=>$cm->id); + $this->gotdata=false; + return; + } + + // Missing basic data from course_modules + if(!isset($cm->availablefrom) || !isset($cm->availableuntil) || + !isset($cm->showavailability) || !isset($cm->course)) { + if($expectingmissingid,'','','','', + 'id,course,availablefrom,availableuntil,showavailability'); + } + + $this->cm=clone($cm); + $this->gotdata=true; + + // Missing extra data + if(!isset($cm->conditionsgrade) || !isset($cm->conditionscompletion)) { + if($expectingmissingcm); + } + } + + /** + * Adds the extra availability conditions (if any) into the given + * course-module object. + * + * @param object &$cm Moodle course-module data object + */ + public static function fill_availability_conditions(&$cm) { + if(empty($cm->id)) { + throw new coding_exception("Invalid parameters; course-module ID not included"); + } + + // Does nothing if the variables are already present + if(!isset($cm->conditionsgrade) || + !isset($cm->conditionscompletion)) { + $cm->conditionsgrade=array(); + $cm->conditionscompletion=array(); + + global $CFG; + $conditions=get_records_sql(" +SELECT + cma.id as cmaid, gi.*,cma.sourcecmid,cma.requiredcompletion,cma.gradeitemid, + cma.grademin as conditiongrademin, cma.grademax as conditiongrademax +FROM + {$CFG->prefix}course_modules_availability cma + LEFT JOIN {$CFG->prefix}grade_items gi ON gi.id=cma.gradeitemid +WHERE + coursemoduleid={$cm->id}"); + $conditions=$conditions ? $conditions : array(); + foreach($conditions as $condition) { + if(!is_null($condition->sourcecmid)) { + $cm->conditionscompletion[$condition->sourcecmid]= + $condition->requiredcompletion; + } else { + $minmax=new stdClass; + $minmax->min=$condition->conditiongrademin; + $minmax->max=$condition->conditiongrademax; + $minmax->name=self::get_grade_name($condition); + $cm->conditionsgrade[$condition->gradeitemid]=$minmax; + } + } + } + } + + /** + * Obtains the name of a grade item. + * @param object $gradeitemobj Object from get_record on grade_items table, + * (can be empty if you want to just get !missing) + * @return string Name of item of !missing if it didn't exist + */ + private static function get_grade_name($gradeitemobj) { + global $CFG; + if(isset($gradeitemobj->id)) { + require_once($CFG->libdir.'/gradelib.php'); + $item=new grade_item; + grade_object::set_properties($item,$gradeitemobj); + return $item->get_name(); + } else { + return '!missing'; // Ooops, missing grade + } + } + + /** + * @return A course-module object with all the information required to + * determine availability. + * @throws coding_exception If data wasn't loaded + */ + public function get_full_course_module() { + $this->require_data(); + return $this->cm; + } + + /** + * Adds to the database a condition based on completion of another module. + * @param int $cmid ID of other module + * @param int $requiredcompletion COMPLETION_xx constant + */ + public function add_completion_condition($cmid,$requiredcompletion) { + // Add to DB + insert_record('course_modules_availability', + (object)array('coursemoduleid'=>$this->cm->id, + 'sourcecmid'=>$cmid,'requiredcompletion'=>$requiredcompletion), + false); + + // Store in memory too + $this->cm->conditionscompletion[$cmid]=$requiredcompletion; + } + + /** + * Adds to the database a condition based on the value of a grade item. + * @param int $gradeitemid ID of grade item + * @param float $min Minimum grade (>=), up to 5 decimal points, or null if none + * @param float $max Maximum grade (<), up to 5 decimal points, or null if none + * @param bool $updateinmemory If true, updates data in memory; otherwise, + * memory version may be out of date (this has performance consequences, + * so don't do it unless it really needs updating) + */ + public function add_grade_condition($gradeitemid,$min,$max,$updateinmemory=false) { + // Normalise nulls + if($min==='') { + $min=null; + } + if($max==='') { + $max=null; + } + // Add to DB + insert_record('course_modules_availability', + (object)array('coursemoduleid'=>$this->cm->id, + 'gradeitemid'=>$gradeitemid,'grademin'=>$min,'grademax'=>$max), + false); + + // Store in memory too + if($updateinmemory) { + $this->cm->conditionsgrade[$gradeitemid]=(object)array( + 'min'=>$min,'max'=>$max); + $this->cm->conditionsgrade[$gradeitemid]->name= + self::get_grade_name(get_record('grade_items', + 'id',$gradeitemid)); + } + } + + /** + * Erases from the database all conditions for this activity. + */ + public function wipe_conditions() { + // Wipe from DB + delete_records('course_modules_availability', + 'coursemoduleid',$this->cm->id); + + // And from memory + $this->cm->conditionsgrade=array(); + $this->cm->conditionscompletion=array(); + } + + /** + * Obtains a string describing all availability restrictions (even if + * they do not apply any more). + * @param object $modinfo Usually leave as null for default. Specify when + * calling recursively from inside get_fast_modinfo. The value supplied + * here must include list of all CMs with 'id' and 'name' + * @return string Information string (for admin) about all restrictions on + * this item + * @throws coding_exception If data wasn't loaded + */ + public function get_full_information($modinfo=null) { + $this->require_data(); + global $COURSE; + + $information=''; + + // Completion conditions + if(count($this->cm->conditionscompletion)>0) { + if($this->cm->course==$COURSE->id) { + $course=$COURSE; + } else { + $course=get_record('course','id',$this->cm->course,'','','','','id,enablecompletion,modinfo'); + } + foreach($this->cm->conditionscompletion as $cmid=>$expectedcompletion) { + if(!$modinfo) { + $modinfo=get_fast_modinfo($course); + } + $information.=get_string( + 'requires_completion_'.$expectedcompletion, + 'condition',$modinfo->cms[$cmid]->name).' '; + } + } + + // Grade conditions + if(count($this->cm->conditionsgrade)>0) { + foreach($this->cm->conditionsgrade as $gradeitemid=>$minmax) { + // String depends on type of requirement. We are coy about + // the actual numbers, in case grades aren't released to + // students. + if(is_null($minmax->min) && is_null($minmax->max)) { + $string='any'; + } else if(is_null($minmax->max)) { + $string='min'; + } else if(is_null($minmax->min)) { + $string='max'; + } else { + $string='range'; + } + $information.=get_string('requires_grade_'.$string,'condition',$minmax->name).' '; + } + } + + // Dates + if($this->cm->availablefrom) { + $information.=get_string('requires_date','condition',userdate( + $this->cm->availablefrom,get_string('strftimedate','langconfig'))); + } + + if($this->cm->availableuntil) { + $information.=get_string('requires_date_before','condition',userdate( + $this->cm->availableuntil,get_string('strftimedate','langconfig'))); + } + + $information=trim($information); + return $information; + } + + /** + * Determines whether this particular course-module is currently available + * according to these criteria. + * + * - This does not include the 'visible' setting (i.e. this might return + * true even if visible is false); visible is handled independently. + * - This does not take account of the viewhiddenactivities capability. + * That should apply later. + * + * @param string &$information If the item has availability restrictions, + * a string that describes the conditions will be stored in this variable; + * if this variable is set blank, that means don't display anything + * @param bool $grabthelot Performance hint: if true, caches information + * required for all course-modules, to make the front page and similar + * pages work more quickly (works only for current user) + * @param int $userid If set, specifies a different user ID to check availability for + * @param object $modinfo Usually leave as null for default. Specify when + * calling recursively from inside get_fast_modinfo. The value supplied + * here must include list of all CMs with 'id' and 'name' + * @return bool True if this item is available to the user, false otherwise + * @throws coding_exception If data wasn't loaded + */ + public function is_available(&$information,$grabthelot=false,$userid=0,$modinfo=null) { + $this->require_data(); + global $COURSE; + + $available=true; + $information=''; + + // Check each completion condition + if(count($this->cm->conditionscompletion)>0) { + if($this->cm->course==$COURSE->id) { + $course=$COURSE; + } else { + $course=get_record('course','id',$this->cm->course,'','','','','id,enablecompletion,modinfo'); + } + + foreach($this->cm->conditionscompletion as $cmid=>$expectedcompletion) { + // The completion system caches its own data + $completiondata=completion_get_data($course,(object)array('id'=>$cmid), + $grabthelot,$userid,$modinfo); + + $thisisok=true; + if($expectedcompletion==COMPLETION_COMPLETE) { + // 'Complete' also allows the pass, fail states + switch($completiondata->completionstate) { + case COMPLETION_COMPLETE: + case COMPLETION_COMPLETE_FAIL: + case COMPLETION_COMPLETE_PASS: + break; + default: + $thisisok=false; + } + } else { + // Other values require exact match + if($completiondata->completionstate!=$expectedcompletion) { + $thisisok=false; + } + } + if(!$thisisok) { + $available=false; + if(!$modinfo) { + $modinfo=get_fast_modinfo($course); + } + $information.=get_string( + 'requires_completion_'.$expectedcompletion, + 'condition',$modinfo->cms[$cmid]->name).' '; + } + } + } + + // Check each grade condition + if(count($this->cm->conditionsgrade)>0) { + foreach($this->cm->conditionsgrade as $gradeitemid=>$minmax) { + $score=$this->get_cached_grade_score($gradeitemid,$grabthelot,$userid); + if($score===false || + (!is_null($minmax->min) && $score<$minmax->min) || + (!is_null($minmax->max) && $score>=$minmax->max)) { + // Grade fail + $available=false; + // String depends on type of requirement. We are coy about + // the actual numbers, in case grades aren't released to + // students. + if(is_null($minmax->min) && is_null($minmax->max)) { + $string='any'; + } else if(is_null($minmax->max)) { + $string='min'; + } else if(is_null($minmax->min)) { + $string='max'; + } else { + $string='range'; + } + $information.=get_string('requires_grade_'.$string,'condition',$minmax->name).' '; + } + } + } + + // Test dates + if($this->cm->availablefrom) { + if(time() < $this->cm->availablefrom) { + $available=false; + $information.=get_string('requires_date','condition',userdate( + $this->cm->availablefrom,get_string('strftimedate','langconfig'))); + } + } + + if($this->cm->availableuntil) { + if(time() >= $this->cm->availableuntil) { + $available=false; + // But we don't display any information about this case. This is + // because the only reason to set a 'disappear' date is usually + // to get rid of outdated information/clutter in which case there + // is no point in showing it... + + // Note it would be nice if we could make it so that the 'until' + // date appears below the item while the item is still accessible, + // unfortunately this is not possible in the current system. Maybe + // later, or if somebody else wants to add it. + } + } + + $information=trim($information); + return $available; + } + + /** + * @return bool True if information about availability should be shown to + * normal users + * @throws coding_exception If data wasn't loaded + */ + public function show_availability() { + $this->require_data(); + return $this->cm->showavailability; + } + + /** + * Internal function cheks that data was loaded. + * @throws coding_exception If data wasn't loaded + */ + private function require_data() { + if(!$this->gotdata) { + throw new coding_exception('Error: cannot call when info was '. + 'constructed without data'); + } + } + + /** + * Obtains a grade score. Note that this score should not be displayed to + * the user, because gradebook rules might prohibit that. It may be a + * non-final score subject to adjustment later. + * + * @param int $gradeitemid Grade item ID we're interested in + * @param bool $grabthelot If true, grabs all scores for current user on + * this course, so that later ones come from cache + * @param int $userid Set if requesting grade for a different user (does + * not use cache) + * @return float Grade score, or false if user does not have a grade yet + */ + private function get_cached_grade_score($gradeitemid,$grabthelot=false,$userid=0) { + global $USER, $SESSION, $CFG; + if($userid==0 || $userid=$USER->id) { + // For current user, go via cache in session + if(empty($SESSION->gradescorecache) || $SESSION->gradescorecacheuserid!=$USER->id) { + $SESSION->gradescorecache=array(); + $SESSION->gradescorecacheuserid=$USER->id; + } + if(!array_key_exists($gradeitemid,$SESSION->gradescorecache)) { + if($grabthelot) { + // Get all grades for the current course + $rs=get_recordset_sql(" +SELECT + gi.id,gg.finalgrade +FROM + {$CFG->prefix}grade_items gi + LEFT JOIN {$CFG->prefix}grade_grades gg ON gi.id=gg.itemid AND gg.userid={$USER->id} +WHERE + gi.courseid={$this->cm->course}"); + while($record=rs_fetch_next_record($rs)) { + $SESSION->gradescorecache[$record->id]= + is_null($record->finalgrade) + ? false + : $record->finalgrade; + + } + rs_close($rs); + // And if it's still not set, well it doesn't exist (eg + // maybe the user set it as a condition, then deleted the + // grade item) so we call it false + if(!array_key_exists($gradeitemid,$SESSION->gradescorecache)) { + $SESSION->gradescorecache[$gradeitemid]=false; + } + } else { + // Just get current grade + $score=get_field('grade_grades','finalgrade', + 'userid',$USER->id,'itemid',$gradeitemid); + // Treat the case where row exists but is null, same as + // case where row doesn't exist + if(is_null($score)) { + $score=false; + } + $SESSION->gradescorecache[$gradeitemid]=$score; + } + } + return $SESSION->gradescorecache[$gradeitemid]; + } else { + // Not the current user, so request the score individually + $score=get_field('grade_grades','finalgrade', + 'userid',$userid,'itemid',$gradeitemid); + if($score===null) { + $score=false; + } + return $score; + } + } + + /** For testing only. Wipes information cached in user session. */ + static function wipe_session_cache() { + global $SESSION; + unset($SESSION->gradescorecache); + unset($SESSION->gradescorecacheuserid); + } + + /** + * Utility function called by modedit.php; updates the + * course_modules_availability table based on the module form data. + * + * @param object $cm Course-module with as much data as necessary, min id + * @param unknown_type $fromform + * @param unknown_type $wipefirst + */ + public static function update_cm_from_form($cm,$fromform,$wipefirst=true) { + $ci=new condition_info($cm,CONDITION_MISSING_EVERYTHING,false); + if($wipefirst) { + $ci->wipe_conditions(); + } + foreach($fromform->conditiongradegroup as $record) { + if($record['conditiongradeitemid']) { + $ci->add_grade_condition($record['conditiongradeitemid'], + $record['conditiongrademin'],$record['conditiongrademax']); + } + } + if(isset($fromform->conditioncompletiongroup)) { + foreach($fromform->conditioncompletiongroup as $record) { + if($record['conditionsourcecmid']) { + $ci->add_completion_condition($record['conditionsourcecmid'], + $record['conditionrequiredcompletion']); + } + } + } + } +} +?>