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 "
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 @@ -