diff --git a/course/editsection.php b/course/editsection.php
index e9a065b..27491b4 100644
--- a/course/editsection.php
+++ b/course/editsection.php
@@ -26,6 +26,10 @@
require_once("../config.php");
require_once("lib.php");
require_once($CFG->libdir.'/filelib.php');
+require_once($CFG->libdir.'/gradelib.php');
+require_once($CFG->libdir.'/completionlib.php');
+require_once($CFG->libdir.'/conditionlib_section.php');
+
require_once('editsection_form.php');
$id = required_param('id',PARAM_INT); // Week/topic ID
@@ -42,8 +46,50 @@ require_capability('moodle/course:update', $context);
$editoroptions = array('context'=>$context ,'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
$section = file_prepare_standard_editor($section, 'summary', $editoroptions, $context, 'course', 'section', $section->id);
$section->usedefaultname = (is_null($section->name));
+if (!empty($CFG->enableavailability)) {
+ if ($data_dt = $DB->get_record('course_sections_availability_dt', array('coursesectionid' => $section->id), '*'))
+ {
+ $section->groupingid = $data_dt->groupingid;
+ $section->availablefrom = $data_dt->availablefrom;
+ $section->availableuntil = $data_dt->availableuntil;
+ $section->showavailability = $data_dt->showavailability;
+ $section->coursesectionid = $section->id;
+ }
+
+ $conditions = $DB->get_records_sql($sql="
+SELECT
+csacg.id as csacgid, gi.*,csacg.sourcecmid as sourcecmid,csacg.requiredcompletion as requiredcompletion, csacg.gradeitemid as gradeitemid,
+csacg.grademin as conditiongrademin, csacg.grademax as conditiongrademax
+FROM
+{course_sections_availability_cg} csacg
+LEFT JOIN {grade_items} gi ON gi.id=csacg.gradeitemid
+WHERE
+coursesectionid=?",array($section->id));
+ $countcompletions = $countgrades = 0;
+ foreach ($conditions as $condition) {
+ if (!is_null($condition->sourcecmid)) {
+ $section->conditioncompletiongroup[$countcompletions]['conditionsourcecmid'] = $condition->sourcecmid;
+ $section->conditioncompletiongroup[$countcompletions]['conditionrequiredcompletion'] = $condition->requiredcompletion;
+ $countcompletions++;
+ } else {
+ $minmax = new stdClass;
+ $minmax->min = $condition->conditiongrademin;
+ $minmax->max = $condition->conditiongrademax;
+ //$minmax->name = condition_info_section::get_grade_name($condition);
+ $section->conditiongradegroup[$condition->gradeitemid] = $minmax;
+ $countgrades++;
+ }
+ }
+ $section->conditioncompletionrepeats = $countcompletions;
+ $section->conditiongraderepeats = $countgrades;
+}
+
$mform = new editsection_form(null, array('course'=>$course, 'editoroptions'=>$editoroptions));
$mform->set_data($section); // set current value
+$mform->completionrepeats = $countcompletions;
+$mform->graderepeats = $countgrades;
+$mform->cs = $section;
+$mform->showavailability = isset($section->showavailability) ? $section->showavailability : null;
/// If data submitted, then process and store.
if ($mform->is_cancelled()){
@@ -59,6 +105,50 @@ if ($mform->is_cancelled()){
$section->summary = $data->summary;
$section->summaryformat = $data->summaryformat;
$DB->update_record('course_sections', $section);
+ if (!empty($CFG->enableavailability)) {
+ //inserting or updating date-time and show avalability
+ if ($data_dt!==false){
+ $data_dt->groupingid = $data->groupingid;
+ $data_dt->availablefrom = $data->availablefrom;
+ $data_dt->availableuntil = $data->availableuntil;
+ $data_dt->showavailability = $data->showavailability;
+ $data_dt->coursesectionid = $section->id;
+ $DB->update_record('course_sections_availability_dt', $data_dt);
+ } else {
+ $data_dt = new stdClass;
+ $data_dt->groupingid = $data->groupingid;
+ $data_dt->availablefrom = $data->availablefrom;
+ $data_dt->availableuntil = $data->availableuntil;
+ $data_dt->showavailability = $data->showavailability;
+ $data_dt->coursesectionid = $section->id;
+ $DB->insert_record_raw('course_sections_availability_dt', $data_dt);
+ }
+ //updating grade & completion conditions table
+ //first let's delete existing conditions for his section from db
+ $DB->delete_records('course_sections_availability_cg', array('coursesectionid' => $section->id));
+ //now insert new conditions received from user
+ foreach ($data->conditiongradegroup as $groupvalue){
+ if ($groupvalue['conditiongradeitemid']>0){
+ $data_cg = new stdClass;
+ $data_cg->coursesectionid = $section->id;
+ $data_cg->gradeitemid = $groupvalue['conditiongradeitemid'];
+ $data_cg->grademin = $groupvalue['conditiongrademin'];
+ $data_cg->grademax = $groupvalue['conditiongrademax'];
+ $DB->insert_record_raw('course_sections_availability_cg', $data_cg);
+ }
+ }
+ foreach ($data->conditioncompletiongroup as $groupvalue){
+ if ($groupvalue['conditionsourcecmid']>0){
+ $data_cg = new stdClass;
+ $data_cg->coursesectionid = $section->id;
+ $data_cg->sourcecmid = $groupvalue['conditionsourcecmid'];
+ $data_cg->requiredcompletion = $groupvalue['conditionrequiredcompletion'];
+ $DB->insert_record_raw('course_sections_availability_cg', $data_cg);
+ }
+ }
+
+ }
+
add_to_log($course->id, "course", "editsection", "editsection.php?id=$section->id", "$section->section");
$PAGE->navigation->clear_cache();
redirect("view.php?id=$course->id");
diff --git a/course/editsection_form.php b/course/editsection_form.php
index ab26049..ce285d2 100644
--- a/course/editsection_form.php
+++ b/course/editsection_form.php
@@ -8,12 +8,15 @@ require_once($CFG->libdir.'/formslib.php');
class editsection_form extends moodleform {
+ public $cs;
+ public $completionrepeats;
+ public $graderepeats;
+ public $showavailability;
+
function definition() {
- global $CFG, $DB;
$mform = $this->_form;
$course = $this->_customdata['course'];
-
$mform->addElement('checkbox', 'usedefaultname', get_string('sectionusedefaultname'));
$mform->setDefault('usedefaultname', true);
@@ -29,9 +32,162 @@ class editsection_form extends moodleform {
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
+
+ $mform->_registerCancelButton('cancel');
+
+ }
+
+ function definition_after_data() {
+ global $CFG, $DB;
+
+ $mform = $this->_form;
+ $course = $this->_customdata['course'];
+
+ if (!empty($CFG->enableavailability)) {
+ // Conditional availability
+
+ $options = array();
+ $options[0] = get_string('none');
+ if ($groupings = $DB->get_records('groupings', array('courseid'=>$course->id))) {
+ foreach ($groupings as $grouping) {
+ $options[$grouping->id] = format_string($grouping->name);
+ }
+ }
+ $mform->addElement('header', '', get_string('availabilityconditions', 'condition'));
+ $mform->addElement('select', 'groupingid', get_string('groupingsection', 'group'), $options);
+ $mform->addHelpButton('groupingid', 'groupingsection', 'group');
+ $mform->addElement('date_time_selector', 'availablefrom', get_string('availablefrom', 'condition'), array('optional'=>true));
+ $mform->addElement('date_time_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true));
+
+ // Conditions based on grades
+ $gradeoptions = array();
+ $items = grade_item::fetch_all(array('courseid'=>$course->id));
+ $items = $items ? $items : array();
+ foreach($items as $id=>$item) {
+ // Do not include grades for current item - TO DO!
+ $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));
+ $grouparray[] =& $mform->createElement('static', '', '','%');
+ $mform->setType('conditiongrademin',PARAM_FLOAT);
+ $mform->setType('conditiongrademax',PARAM_FLOAT);
+ $group = $mform->createElement('group','conditiongradegroup',
+ get_string('gradecondition', 'condition'),$grouparray);
+
+ if(!$this->graderepeats) {
+ $count = 1;
+ } else {
+ $count = $this->graderepeats + 1;
+ }
+
+ $this->repeat_elements(array($group), $count, array(), 'conditiongraderepeats', 'conditiongradeadds', 2,
+ get_string('addgrades', 'condition'), true);
+ $mform->addHelpButton('conditiongradegroup[0]', 'gradeconditionsection', 'condition');
+
+ // Conditions based on completion
+ $completion = new completion_info($course);
+ if ($completion->is_enabled()) {
+ $completionoptions = array();
+ $modinfo = get_fast_modinfo($course);
+ foreach($modinfo->cms as $id=>$cm) {
+ // Add each course-module if it:
+ // (a) has completion turned on
+ // (b) does not belong to current course-section
+ if ($cm->completion && (empty($course) || $this->cs->id != $cm->section)) {
+ $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);
+
+ if(!$this->completionrepeats) {
+ $count = 1;
+ } else {
+ $count = $this->completionrepeats + 1;
+ }
+ $this->repeat_elements(array($group),$count,array(),
+ 'conditioncompletionrepeats','conditioncompletionadds',2,
+ get_string('addcompletions','condition'),true);
+ $mform->addHelpButton('conditioncompletiongroup[0]', 'completionconditionsection', 'condition');
+ }
+
+ // Availability conditions - set up form values
+ if (!empty($CFG->enableavailability) && $this->cs) {
+ $ci = new condition_info_section($this->cs);
+ $fullcm=$ci->get_full_course_section();
+
+ $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()) {
+ $num=0;
+ foreach($fullcm->conditionscompletion as $othercmid=>$state) {
+ $groupelements=$mform->getElement('conditioncompletiongroup['.$num.']')->getElements();
+ $groupelements[0]->setValue($othercmid);
+ $groupelements[1]->setValue($state);
+ $num++;
+ }
+ }
+ }
+
+
+ // Do we display availability info to students?
+ $mform->addElement('select', 'showavailability', get_string('showavailabilitysection', 'condition'),
+ array(CONDITION_STUDENTVIEW_SHOW=>get_string('showavailabilitysection_show', 'condition'),
+ CONDITION_STUDENTVIEW_HIDE=>get_string('showavailabilitysection_hide', 'condition')));
+
+ if (isset($this->showavailability)) {
+ $mform->setDefault('showavailability', $this->showavailability);
+ } else {
+ $mform->setDefault('showavailability', CONDITION_STUDENTVIEW_SHOW);
+ }
+ }
+
//--------------------------------------------------------------------------------
$this->add_action_buttons();
}
+
+ // form verification
+ function validation($data, $files) {
+ $errors = Array();
+ // Conditions: Don't let them set dates which make no sense
+ if (array_key_exists('availablefrom', $data) &&
+ $data['availablefrom'] && $data['availableuntil'] &&
+ $data['availablefrom'] > $data['availableuntil']) {
+ $errors['availablefrom'] = get_string('badavailabledates', 'condition');
+ }
+
+ return $errors;
+ }
+
}
diff --git a/course/format/topics/format.php b/course/format/topics/format.php
index aa1004f..eb4c7c1 100644
--- a/course/format/topics/format.php
+++ b/course/format/topics/format.php
@@ -136,7 +136,9 @@ while ($section <= $course->numsections) {
if (!empty($sections[$section])) {
$thissection = $sections[$section];
-
+ //Checking availability conditions
+ $si = new condition_info_section($thissection);
+ $thissection->is_available = $si->is_available($thissection->information, true, $USER->id); //if not available 'information' will tell why
} else {
$thissection = new stdClass;
$thissection->course = $course->id; // Create a new section structure
@@ -148,7 +150,7 @@ while ($section <= $course->numsections) {
$thissection->id = $DB->insert_record('course_sections', $thissection);
}
- $showsection = (has_capability('moodle/course:viewhiddensections', $context) or $thissection->visible or !$course->hiddensections);
+ $showsection = !$course->hiddensections && (has_capability('moodle/course:viewhiddensections', $context) || ($thissection->visible && ($thissection->is_available || $thissection->showavailability)));
if (!empty($displaysection) and $displaysection != $section) { // Check this topic is visible
if ($showsection) {
@@ -215,12 +217,24 @@ while ($section <= $course->numsections) {
echo '';
echo '
';
- if (!has_capability('moodle/course:viewhiddensections', $context) and !$thissection->visible) { // Hidden for students
- echo get_string('notavailable');
+ if (!has_capability('moodle/course:viewhiddensections', $context) && (!$thissection->visible || (!$thissection->is_available && $thissection->showavailability==1)) ) { // Hidden for students
+ echo '
';
+ if (!empty($thissection->information)) {
+ echo $thissection->information;
+ } else {
+ echo get_string('notavailable');
+ }
+ echo '
';
} else {
if (!is_null($thissection->name)) {
echo $OUTPUT->heading($thissection->name, 3, 'sectionname');
}
+ if (!empty($thissection->information))
+ {
+ echo '
';
+ echo $thissection->information;
+ echo '
';
+ }
echo '
';
if ($thissection->summary) {
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
diff --git a/course/format/weeks/format.php b/course/format/weeks/format.php
index 68e66a4..05f42ee 100644
--- a/course/format/weeks/format.php
+++ b/course/format/weeks/format.php
@@ -139,6 +139,9 @@ defined('MOODLE_INTERNAL') || die();
if (!empty($sections[$section])) {
$thissection = $sections[$section];
+ //Checking availability conditions
+ $si = new condition_info_section($thissection);
+ $thissection->is_available = $si->is_available($thissection->information, true, $USER->id); //if not available 'information' will tell why
} else {
unset($thissection);
@@ -151,7 +154,7 @@ defined('MOODLE_INTERNAL') || die();
$thissection->id = $DB->insert_record('course_sections', $thissection);
}
- $showsection = (has_capability('moodle/course:viewhiddensections', $context) or $thissection->visible or !$course->hiddensections);
+ $showsection = !$course->hiddensections && (has_capability('moodle/course:viewhiddensections', $context) || ($thissection->visible && ($thissection->is_available || $thissection->showavailability)));
if (!empty($displaysection) and $displaysection != $section) { // Check this week is visible
if ($showsection) {
@@ -215,15 +218,27 @@ defined('MOODLE_INTERNAL') || die();
$weekperiod = $weekday.' - '.$endweekday;
echo '
';
- if (!has_capability('moodle/course:viewhiddensections', $context) and !$thissection->visible) { // Hidden for students
+ if (!has_capability('moodle/course:viewhiddensections', $context) && (!$thissection->visible || (!$thissection->is_available && $thissection->showavailability==1)) ) { // Hidden for students
echo $OUTPUT->heading($currenttext.$weekperiod.' ('.get_string('notavailable').')', 3, 'weekdates');
-
+ echo '
';
+ if (!empty($thissection->information)) {
+ echo $thissection->information;
+ } else {
+ echo get_string('notavailable');
+ }
+ echo '
';
} else {
if (isset($thissection->name) && ($thissection->name !== NULL)) { // empty string is ok
echo $OUTPUT->heading($thissection->name, 3, 'weekdates');
} else {
echo $OUTPUT->heading($currenttext.$weekperiod, 3, 'weekdates');
}
+ if (!empty($thissection->information))
+ {
+ echo '
';
+ echo $thissection->information;
+ echo '
';
+ }
echo '
';
$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
$summarytext = file_rewrite_pluginfile_urls($thissection->summary, 'pluginfile.php', $coursecontext->id, 'course', 'section', $thissection->id);
diff --git a/course/lib.php b/course/lib.php
index 0f7df68..868c617 100644
--- a/course/lib.php
+++ b/course/lib.php
@@ -1251,8 +1251,17 @@ function get_all_sections($courseid) {
global $DB;
static $coursesections = array();
if (!array_key_exists($courseid, $coursesections)) {
- $coursesections[$courseid] = $DB->get_records("course_sections", array("course"=>"$courseid"), "section",
- "section, id, course, name, summary, summaryformat, sequence, visible");
+ $coursesections[$courseid] = $DB->get_records_sql($sql="
+SELECT
+ cs.section as section, cs.id as id, cs.name as name, cs.summary as summary, cs.summaryformat as summaryformat, cs.sequence as sequence, cs.visible as visible, cs.course as course, csadt.availablefrom as availablefrom, csadt.availableuntil as availableuntil, csadt.showavailability as showavailability, csadt.groupingid as groupingid
+FROM
+ {course_sections} cs
+ LEFT JOIN {course_sections_availability_dt} csadt ON cs.id = csadt.coursesectionid
+WHERE
+ cs.course=?
+ORDER BY
+section",array($courseid));
+
}
return $coursesections[$courseid];
}
diff --git a/course/modedit.php b/course/modedit.php
index cd84c00..97a8073 100644
--- a/course/modedit.php
+++ b/course/modedit.php
@@ -303,10 +303,12 @@ if ($mform->is_cancelled()) {
$cm->availableuntil = $fromform->availableuntil;
// The form time is midnight, but because we want it to be
// inclusive, set it to 23:59:59 on that day.
+ /*
if ($cm->availableuntil) {
$cm->availableuntil = strtotime('23:59:59',
$cm->availableuntil);
}
+ */
$cm->showavailability = $fromform->showavailability;
condition_info::update_cm_from_form($cm,$fromform,true);
}
@@ -389,10 +391,12 @@ if ($mform->is_cancelled()) {
$newcm->availableuntil = $fromform->availableuntil;
// The form time is midnight, but because we want it to be
// inclusive, set it to 23:59:59 on that day.
+ /*
if ($newcm->availableuntil) {
$newcm->availableuntil = strtotime('23:59:59',
$newcm->availableuntil);
}
+ */
$newcm->showavailability = $fromform->showavailability;
}
diff --git a/course/moodleform_mod.php b/course/moodleform_mod.php
index 0482168..632663d 100644
--- a/course/moodleform_mod.php
+++ b/course/moodleform_mod.php
@@ -429,9 +429,9 @@ abstract class moodleform_mod extends moodleform {
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->addElement('date_time_selector', 'availablefrom', get_string('availablefrom', 'condition'), array('optional'=>true));
$mform->addHelpButton('availablefrom', 'availablefrom', 'condition');
- $mform->addElement('date_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true));
+ $mform->addElement('date_time_selector', 'availableuntil', get_string('availableuntil', 'condition'), array('optional'=>true));
// Conditions based on grades
$gradeoptions = array();
diff --git a/course/view.php b/course/view.php
index 28ed124..630e4f2 100644
--- a/course/view.php
+++ b/course/view.php
@@ -5,6 +5,7 @@
require_once('../config.php');
require_once('lib.php');
require_once($CFG->dirroot.'/mod/forum/lib.php');
+ require_once($CFG->libdir.'/conditionlib_section.php');
require_once($CFG->libdir.'/completionlib.php');
$id = optional_param('id', 0, PARAM_INT);
diff --git a/lang/en/condition.php b/lang/en/condition.php
index 5c0fd77..586a1dc 100644
--- a/lang/en/condition.php
+++ b/lang/en/condition.php
@@ -37,6 +37,10 @@ $string['completioncondition'] = 'Activity completion condition';
$string['completioncondition_help'] = 'This setting determines any activity completion conditions which must be met in order to access the activity. Note that completion tracking must first be set before an activity completion condition can be set.
Multiple activity completion conditions may be set if desired. If so, access to the activity will only be permitted when ALL activity completion conditions are met.';
+$string['completionconditionsection'] = 'Activity completion condition';
+$string['completionconditionsection_help'] = 'This setting determines any activity completion conditions which must be met in order to access the section. Note that completion tracking must first be set before an activity completion condition can be set.
+
+Multiple activity completion conditions may be set if desired. If so, access to the section will only be permitted when ALL activity completion conditions are met.';
$string['completion_fail'] = 'must be complete with fail grade';
$string['completion_incomplete'] = 'must not be marked complete';
$string['completion_pass'] = 'must be complete with pass grade';
@@ -47,6 +51,10 @@ $string['gradecondition'] = 'Grade condition';
$string['gradecondition_help'] = 'This setting determines any grade conditions which must be met in order to access the activity.
Multiple grade conditions may be set if desired. If so, the activity will only allow access when ALL grade conditions are met.';
+$string['gradeconditionsection'] = 'Grade condition';
+$string['gradeconditionsection_help'] = 'This setting determines any grade conditions which must be met in order to access the section.
+
+Multiple grade conditions may be set if desired. If so, the section will only allow access when ALL grade conditions are met.';
$string['grade_upto'] = 'and less than';
$string['none'] = '(none)';
$string['notavailableyet'] = 'Not available yet';
@@ -62,7 +70,11 @@ $string['requires_grade_max'] = 'Not available unless you get an appropriate sco
$string['requires_grade_min'] = 'Not available until you achieve a required score in
{$a}.';
$string['requires_grade_range'] = 'Not available unless you get a particular score in
{$a}.';
$string['showavailability'] = 'Before activity can be accessed';
+$string['showavailabilitysection'] = 'Before section can be accessed';
$string['showavailability_hide'] = 'Hide activity entirely';
$string['showavailability_show'] = 'Show activity greyed-out, with restriction information';
+$string['showavailabilitysection_hide'] = 'Hide section entirely';
+$string['showavailabilitysection_show'] = 'Show section greyed-out, with restriction information';
$string['userrestriction_hidden'] = 'Restricted (completely hidden, no message): ‘{$a}’';
$string['userrestriction_visible'] = 'Restricted: ‘{$a}’';
+$string['groupingnoaccess'] = 'You have to become a member of the group which has access to this section.';
\ No newline at end of file
diff --git a/lang/en/group.php b/lang/en/group.php
index 7a98c5b..1505986 100644
--- a/lang/en/group.php
+++ b/lang/en/group.php
@@ -76,6 +76,8 @@ $string['groupinfomembers'] = 'Info about selected members';
$string['groupinfopeople'] = 'Info about selected people';
$string['grouping'] = 'Grouping';
$string['grouping_help'] = 'A grouping is a collection of groups within a course. If a grouping is selected, students assigned to groups within the grouping will be able to work together.';
+$string['groupingsection'] = 'Grouping access';
+$string['groupingsection_help'] = 'A grouping is a collection of groups within a course. If a grouping is selected here, only students assigned to groups within this grouping will have access to the section.';
$string['groupingdescription'] = 'Grouping description';
$string['groupingname'] = 'Grouping name';
$string['groupingnameexists'] = 'The grouping name \'{$a}\' already exists in this course, please choose another one.';
diff --git a/lib/conditionlib.php b/lib/conditionlib.php
index 83b79d3..208fdfb 100644
--- a/lib/conditionlib.php
+++ b/lib/conditionlib.php
@@ -26,31 +26,33 @@
defined('MOODLE_INTERNAL') || die();
-/** The activity is not displayed to students at all when conditions aren't met. */
-define('CONDITION_STUDENTVIEW_HIDE',0);
-/** The activity is displayed to students as a greyed-out name, with informational
- text that explains the conditions under which it will be available. */
-define('CONDITION_STUDENTVIEW_SHOW',1);
-
-/** The $cm variable is expected to contain all completion-related data */
-define('CONDITION_MISSING_NOTHING',0);
-/** The $cm variable is expected to contain the fields from course_modules but
- not the course_modules_availability data */
-define('CONDITION_MISSING_EXTRATABLE',1);
-/** The $cm variable is expected to contain nothing except the ID */
-define('CONDITION_MISSING_EVERYTHING',2);
-
-require_once($CFG->libdir.'/completionlib.php');
+if (!defined('CONDITION_STUDENTVIEW_HIDE')) {
+ /** The activity is not displayed to students at all when conditions aren't met. */
+ define('CONDITION_STUDENTVIEW_HIDE',0);
+ /** The activity is displayed to students as a greyed-out name, with informational
+ text that explains the conditions under which it will be available. */
+ define('CONDITION_STUDENTVIEW_SHOW',1);
+
+ /** The $cm variable is expected to contain all completion-related data */
+ define('CONDITION_MISSING_NOTHING',0);
+ /** The $cm variable is expected to contain the fields from course_modules but
+ not the course_modules_availability data */
+ define('CONDITION_MISSING_EXTRATABLE',1);
+ /** The $cm variable is expected to contain nothing except the ID */
+ define('CONDITION_MISSING_EVERYTHING',2);
+
+ require_once($CFG->libdir.'/completionlib.php');
-/**
- * @global stdClass $CONDITIONLIB_PRIVATE
- * @name $CONDITIONLIB_PRIVATE
- */
-global $CONDITIONLIB_PRIVATE;
-$CONDITIONLIB_PRIVATE = new stdClass;
-// Caches whether completion values are used in availability conditions.
-// Array of course => array of cmid => true.
-$CONDITIONLIB_PRIVATE->usedincondition = array();
+ /**
+ * @global stdClass $CONDITIONLIB_PRIVATE
+ * @name $CONDITIONLIB_PRIVATE
+ */
+ global $CONDITIONLIB_PRIVATE;
+ $CONDITIONLIB_PRIVATE = new stdClass;
+ // Caches whether completion values are used in availability conditions.
+ // Array of course => array of cmid => true.
+ $CONDITIONLIB_PRIVATE->usedincondition = array();
+}
/**
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -675,7 +677,7 @@ WHERE
public static function completion_value_used_as_condition($course, $cm) {
// Have we already worked out a list of required completion values
// for this course? If so just use that
- global $CONDITIONLIB_PRIVATE;
+ global $CONDITIONLIB_PRIVATE, $DB;
if (!array_key_exists($course->id, $CONDITIONLIB_PRIVATE->usedincondition)) {
// We don't have data for this course, build it
$modinfo = get_fast_modinfo($course);
@@ -686,6 +688,12 @@ WHERE
}
}
}
- return array_key_exists($cm->id, $CONDITIONLIB_PRIVATE->usedincondition[$course->id]);
+ $founddependant = array_key_exists($cm->id, $CONDITIONLIB_PRIVATE->usedincondition[$course->id]);
+ if (!$founddependant) {
+ if ($DB->record_exists('course_sections_availability_cg', array('sourcecmid'=>$cm->id)) > 0 ) {
+ $founddependant = true;
+ }
+ }
+ return $founddependant;
}
}
diff --git a/lib/conditionlib_section.php b/lib/conditionlib_section.php
new file mode 100644
index 0000000..ff03d3d
--- /dev/null
+++ b/lib/conditionlib_section.php
@@ -0,0 +1,719 @@
+.
+
+/**
+ * Used for tracking conditions that apply before sections are displayed
+ * to students ('conditional availability').
+ *
+ * @package core
+ * @subpackage condition
+ * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+if (!defined('CONDITION_STUDENTVIEW_HIDE')){
+
+ /** The section is not displayed to students at all when conditions aren't met. */
+ define('CONDITION_STUDENTVIEW_HIDE',0);
+ /** The section is displayed to students as a greyed-out name, with informational
+ text that explains the conditions under which it will be available. */
+ define('CONDITION_STUDENTVIEW_SHOW',1);
+
+ /** The $cs variable is expected to contain all completion-related data */
+ define('CONDITION_MISSING_NOTHING',0);
+ /** The $cs variable is expected to contain the fields from course_sections but
+ not the course_sections_availability_* data */
+ define('CONDITION_MISSING_EXTRATABLE',1);
+ /** The $cs variable is expected to contain nothing except the ID */
+ define('CONDITION_MISSING_EVERYTHING',2);
+
+ require_once($CFG->libdir.'/completionlib.php');
+
+ /**
+ * @global stdClass $CONDITIONLIB_PRIVATE
+ * @name $CONDITIONLIB_PRIVATE
+ */
+ global $CONDITIONLIB_PRIVATE;
+ $CONDITIONLIB_PRIVATE = new stdClass;
+ // Caches whether completion values are used in availability conditions.
+ // Array of course => array of cmid => true.
+ $CONDITIONLIB_PRIVATE->usedincondition = array();
+}
+
+/**
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package moodlecore
+ */
+class condition_info_section {
+ /**
+ * @var object, bool
+ */
+ private $cs, $gotdata;
+
+ /**
+ * Constructs with course-section details.
+ *
+ * @global object
+ * @uses CONDITION_MISSING_NOTHING
+ * @uses CONDITION_MISSING_EVERYTHING
+ * @uses DEBUG_DEVELOPER
+ * @uses CONDITION_MISSING_EXTRATABLE
+ * @param object $cs Moodle course-section object. 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($cs, $expectingmissing=CONDITION_MISSING_NOTHING,
+ $loaddata=true) {
+ global $DB;
+
+ // Check ID as otherwise we can't do the other queries
+ if (empty($cs->id)) {
+ throw new coding_exception("Invalid parameters; course-section ID not included");
+ }
+
+ // If not loading data, don't do anything else
+ if (!$loaddata) {
+ $this->cs = (object)array('id'=>$cs->id);
+ $this->gotdata = false;
+ return;
+ }
+
+ // Missing basic data from course_sections
+ if (!isset($cs->course) or !isset($cs->availablefrom) or !isset($cs->availableuntil) or !isset($cs->availableuntil) or !isset($cs->showavailability)) {
+ /*
+ if ($expectingmissing
get_record('course_sections',array('id'=>$cs->id), 'id,course');
+ */
+ $cs = $DB->get_record_sql($sql="
+SELECT
+ cs.id, cs.course, csadt.availablefrom, csadt.availableuntil, csadt.showavailability, csadt.groupingid as groupingid
+FROM
+ {course_sections} cs
+ LEFT JOIN {course_sections_availability_dt} csadt ON cs.id = csadt.coursesectionid
+WHERE
+ cs.id=?",array($cs->id));
+
+ }
+
+ $this->cs = clone($cs);
+ $this->gotdata = true;
+
+ // Missing extra data
+ if (!isset($cs->conditionsgrade) || !isset($cs->conditionscompletion)) {
+ /*
+ if ($expectingmissingcs);
+ }
+
+ }
+
+ /**
+ * Adds the extra availability conditions (if any) into the given
+ * course-section object.
+ *
+ * @global object
+ * @global object
+ * @param object $cs Moodle course-section data object
+ */
+ public static function fill_availability_conditions(&$cs) {
+ if (empty($cs->id)) {
+ throw new coding_exception("Invalid parameters; course-section ID not included");
+ }
+
+ // Does nothing if the variables are already present
+ if (!isset($cs->conditionsgrade) ||
+ !isset($cs->conditionscompletion)) {
+ $cs->conditionsgrade=array();
+ $cs->conditionscompletion=array();
+
+ global $DB, $CFG;
+ $conditions = $DB->get_records_sql($sql="
+SELECT
+ csacg.id as csacgid, gi.*,csacg.sourcecmid,csacg.requiredcompletion,csacg.gradeitemid,
+ csacg.grademin as conditiongrademin, csacg.grademax as conditiongrademax
+FROM
+ {course_sections_availability_cg} csacg
+ LEFT JOIN {grade_items} gi ON gi.id=csacg.gradeitemid
+WHERE
+ coursesectionid=?",array($cs->id));
+ foreach ($conditions as $condition) {
+ if (!is_null($condition->sourcecmid)) {
+ $cs->conditionscompletion[$condition->sourcecmid] =
+ $condition->requiredcompletion;
+ } else {
+ $minmax = new stdClass;
+ $minmax->min = $condition->conditiongrademin;
+ $minmax->max = $condition->conditiongrademax;
+ $minmax->name = self::get_grade_name($condition);
+ $cs->conditionsgrade[$condition->gradeitemid] = $minmax;
+ }
+ }
+ }
+ }
+
+ /**
+ * Obtains the name of a grade item.
+ *
+ * @global object
+ * @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
+ }
+ }
+
+ /**
+ * @see require_data()
+ * @return object A course-section object with all the information required to
+ * determine availability.
+ */
+ public function get_full_course_section() {
+ $this->require_data();
+ return $this->cs;
+ }
+
+ /**
+ * Adds to the database a condition based on completion of a module.
+ *
+ * @global object
+ * @param int $cmid ID of a module
+ * @param int $requiredcompletion COMPLETION_xx constant
+ */
+ public function add_completion_condition($cmid, $requiredcompletion) {
+ // Add to DB
+ global $DB;
+ $DB->insert_record('course_sections_availability_cg',
+ (object)array('coursesectionid'=>$this->cs->id,
+ 'sourcecmid'=>$cmid, 'requiredcompletion'=>$requiredcompletion),
+ false);
+
+ // Store in memory too
+ $this->cs->conditionscompletion[$cmid] = $requiredcompletion;
+ }
+
+ /**
+ * Adds to the database a condition based on the value of a grade item.
+ *
+ * @global object
+ * @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
+ global $DB;
+ $DB->insert_record('course_sections_availability_cg',
+ (object)array('coursesectionid'=>$this->cs->id,
+ 'gradeitemid'=>$gradeitemid, 'grademin'=>$min, 'grademax'=>$max),
+ false);
+
+ // Store in memory too
+ if ($updateinmemory) {
+ $this->cs->conditionsgrade[$gradeitemid]=(object)array(
+ 'min'=>$min, 'max'=>$max);
+ $this->cs->conditionsgrade[$gradeitemid]->name =
+ self::get_grade_name($DB->get_record('grade_items',
+ array('id'=>$gradeitemid)));
+ }
+ }
+
+ /**
+ * Erases from the database all conditions for this section.
+ *
+ * @global object
+ */
+ public function wipe_conditions() {
+ // Wipe from DB
+ global $DB;
+ $DB->delete_records('course_sections_availability_cg',
+ array('coursesectionid'=>$this->cs->id));
+
+ // And from memory
+ $this->cs->conditionsgrade = array();
+ $this->cs->conditionscompletion = array();
+ }
+
+ /**
+ * Obtains a string describing all availability restrictions (even if
+ * they do not apply any more).
+ *
+ * @global object
+ * @global object
+ * @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 CSs with 'id' and 'name'
+ * @return string Information string (for admin) about all restrictions on
+ * this item
+ */
+ public function get_full_information($modinfo=null) {
+ $this->require_data();
+ global $COURSE, $DB;
+
+ $information = '';
+
+ // Completion conditions
+ if(count($this->cs->conditionscompletion)>0) {
+ if ($this->cs->course==$COURSE->id) {
+ $course = $COURSE;
+ } else {
+ $course = $DB->get_record('course',array('id'=>$this->cs->course),'id,enablecompletion,modinfo');
+ }
+ foreach ($this->cs->conditionscompletion as $cmid=>$expectedcompletion) {
+ if (!$modinfo) {
+ $modinfo = get_fast_modinfo($course);
+ }
+ if (empty($modinfo->cms[$cmid])) {
+ continue;
+ }
+ $information .= get_string(
+ 'requires_completion_'.$expectedcompletion,
+ 'condition', $modinfo->cms[$cmid]->name).' ';
+ }
+ }
+
+ // Grade conditions
+ if (count($this->cs->conditionsgrade)>0) {
+ foreach ($this->cs->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->cs->availablefrom && $this->cs->availableuntil) {
+ $information .= get_string('requires_date_both', 'condition',
+ (object)array(
+ 'from' => self::show_time($this->cs->availablefrom, false),
+ 'until' => self::show_time($this->cs->availableuntil, true)));
+ } else if ($this->cs->availablefrom) {
+ $information .= get_string('requires_date', 'condition',
+ self::show_time($this->cs->availablefrom, false));
+ } else if ($this->cs->availableuntil) {
+ $information .= get_string('requires_date_before', 'condition',
+ self::show_time($this->cs->availableuntil, true));
+ }
+
+ $information = trim($information);
+ return $information;
+ }
+
+ /**
+ * Determines whether this particular course-section 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 viewhiddensections capability.
+ * That should apply later.
+ *
+ * @global object
+ * @global object
+ * @uses COMPLETION_COMPLETE
+ * @uses COMPLETION_COMPLETE_FAIL
+ * @uses COMPLETION_COMPLETE_PASS
+ * @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-sections, 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
+ */
+ public function is_available(&$information, $grabthelot=false, $userid=0, $modinfo=null) {
+ $this->require_data();
+ global $COURSE,$DB;
+
+ $available = true;
+ $information = '';
+
+ // Check each completion condition
+ if(count($this->cs->conditionscompletion)>0) {
+ if ($this->cs->course==$COURSE->id) {
+ $course = $COURSE;
+ } else {
+ $course = $DB->get_record('course',array('id'=>$this->cs->course),'id,enablecompletion,modinfo');
+ }
+
+ $completion = new completion_info($course);
+ foreach ($this->cs->conditionscompletion as $cmid=>$expectedcompletion) {
+ // If this depends on a deleted module, handle that situation
+ // gracefully.
+ if (!$modinfo) {
+ $modinfo = get_fast_modinfo($course);
+ }
+ if (empty($modinfo->cms[$cmid])) {
+ global $PAGE, $UNITTEST;
+ if (!empty($UNITTEST) || (isset($PAGE) && strpos($PAGE->pagetype, 'course-view-')===0)) {
+ debugging("Warning: section {$this->cs->id} '{$this->cs->name}' has condition on deleted activity $cmid (to get rid of this message, edit the named section)");
+ }
+ continue;
+ }
+
+ // The completion system caches its own data
+ $completiondata = $completion->get_data((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;
+ $information .= get_string(
+ 'requires_completion_'.$expectedcompletion,
+ 'condition',$modinfo->cms[$cmid]->name).' ';
+ }
+ }
+ }
+
+ // Check each grade condition
+ if (count($this->cs->conditionsgrade)>0) {
+ foreach ($this->cs->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->cs->availablefrom) {
+ if (time() < $this->cs->availablefrom) {
+ $available = false;
+
+ $information .= get_string('requires_date', 'condition',
+ self::show_time($this->cs->availablefrom, false));
+ }
+ }
+
+ if ($this->cs->availableuntil) {
+ if (time() >= $this->cs->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.
+ }
+ }
+
+ // test if user is enrolled to a grouping which has access to the section
+ if ($this->cs->groupingid) {
+ $usergrouping = $DB->get_record_sql($sql="
+SELECT
+ g.id
+FROM
+ {groupings} g
+ LEFT JOIN {groupings_groups} gg ON g.id = gg.groupingid
+ LEFT JOIN {groups_members} gm ON gg.groupid = gm.groupid
+WHERE
+ g.courseid=? AND gm.userid=? AND g.id=?",array($COURSE->id, $userid, $this->cs->groupingid));
+
+ if (!$usergrouping) {
+ $available = false;
+ $information .= get_string('groupingnoaccess', 'condition');
+ }
+ }
+
+ $information=trim($information);
+ return $available;
+ }
+
+ /**
+ * Shows a time either as a date (if it falls exactly on the day) or
+ * a full date and time, according to user's timezone.
+ *
+ * @param int $time Time
+ * @param bool $until True if this date should be treated as the second of
+ * an inclusive pair - if so the time will be shown unless date is 23:59:59.
+ * Without this the date shows for 0:00:00.
+ * @return string Date
+ */
+ private function show_time($time, $until) {
+ // Break down the time into fields
+ $userdate = usergetdate($time);
+
+ // Handle the 'inclusive' second date
+ if($until) {
+ $dateonly = $userdate['hours']==23 && $userdate['minutes']==59 &&
+ $userdate['seconds']==59;
+ } else {
+ $dateonly = $userdate['hours']==0 && $userdate['minutes']==0 &&
+ $userdate['seconds']==0;
+ }
+
+ return userdate($time, get_string(
+ $dateonly ? 'strftimedate' : 'strftimedatetime', 'langconfig'));
+ }
+
+ /**
+ * @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->cs->showavailability;
+ }
+
+ /**
+ * Internal function cheks that data was loaded.
+ *
+ * @return void 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.
+ *
+ * @global object
+ * @global object
+ * @global object
+ * @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 as a percentage in range 0-100 (e.g. 100.0
+ * or 37.21), or false if user does not have a grade yet
+ */
+ private function get_cached_grade_score($gradeitemid, $grabthelot=false, $userid=0) {
+ global $USER, $DB, $SESSION;
+ 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 = $DB->get_recordset_sql("
+SELECT
+ gi.id,gg.finalgrade,gg.rawgrademin,gg.rawgrademax
+FROM
+ {grade_items} gi
+ LEFT JOIN {grade_grades} gg ON gi.id=gg.itemid AND gg.userid=?
+WHERE
+ gi.courseid=?", array($USER->id, $this->cm->course));
+ foreach ($rs as $record) {
+ $SESSION->gradescorecache[$record->id] =
+ is_null($record->finalgrade)
+ // No grade = false
+ ? false
+ // Otherwise convert grade to percentage
+ : (($record->finalgrade - $record->rawgrademin) * 100) /
+ ($record->rawgrademax - $record->rawgrademin);
+
+ }
+ $rs->close();
+ // 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
+ $record = $DB->get_record('grade_grades', array(
+ 'userid'=>$USER->id, 'itemid'=>$gradeitemid));
+ if ($record && !is_null($record->finalgrade)) {
+ $score = (($record->finalgrade - $record->rawgrademin) * 100) /
+ ($record->rawgrademax - $record->rawgrademin);
+ } else {
+ // Treat the case where row exists but is null, same as
+ // case where row doesn't exist
+ $score = false;
+ }
+ $SESSION->gradescorecache[$gradeitemid]=$score;
+ }
+ }
+ return $SESSION->gradescorecache[$gradeitemid];
+ } else {
+ // Not the current user, so request the score individually
+ $record = $DB->get_record('grade_grades', array(
+ 'userid'=>$userid, 'itemid'=>$gradeitemid));
+ if ($record && !is_null($record->finalgrade)) {
+ $score = (($record->finalgrade - $record->rawgrademin) * 100) /
+ ($record->rawgrademax - $record->rawgrademin);
+ } else {
+ // Treat the case where row exists but is null, same as
+ // case where row doesn't exist
+ $score = false;
+ }
+ return $score;
+ }
+ }
+
+ /**
+ * For testing only. Wipes information cached in user session.
+ *
+ * @global object
+ */
+ 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 object $fromform
+ * @param bool $wipefirst Defaults to true
+ */
+ public static function update_cs_from_form($cs, $fromform, $wipefirst=true) {
+ $ci=new condition_info_section($cs, 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']);
+ }
+ }
+ }
+ }
+
+ /**
+ * Used in course/lib.php because we need to disable the completion JS if
+ * a completion value affects a conditional section.
+ *
+ * @global object
+ * @param object $course Moodle course object
+ * @param object $cm Moodle course-module
+ * @return bool True if this is used in a condition, false otherwise
+ */
+ public static function completion_value_used_as_condition($course, $cm) {
+ // Have we already worked out a list of required completion values
+ // for this course? If so just use that
+ global $CONDITIONLIB_PRIVATE;
+ if (!array_key_exists($course->id, $CONDITIONLIB_PRIVATE->usedincondition)) {
+ // We don't have data for this course, build it
+ $modinfo = get_fast_modinfo($course);
+ $CONDITIONLIB_PRIVATE->usedincondition[$course->id] = array();
+ foreach ($modinfo->cms as $othercm) {
+ foreach ($othercm->conditionscompletion as $cmid=>$expectedcompletion) {
+ $CONDITIONLIB_PRIVATE->usedincondition[$course->id][$cmid] = true;
+ }
+ }
+ }
+ return array_key_exists($cm->id, $CONDITIONLIB_PRIVATE->usedincondition[$course->id]);
+ }
+}
diff --git a/lib/navigationlib.php b/lib/navigationlib.php
index 1e4be90..96347e5 100644
--- a/lib/navigationlib.php
+++ b/lib/navigationlib.php
@@ -28,6 +28,9 @@
defined('MOODLE_INTERNAL') || die();
+require_once($CFG->libdir.'/conditionlib_section.php');
+require_once($CFG->libdir.'/completionlib.php');
+
/**
* The name that will be used to separate the navigation cache within SESSION
*/
@@ -1432,7 +1435,16 @@ class global_navigation extends navigation_node {
if ($course->id == SITEID) {
$this->load_section_activities($coursenode, $section->section, $modinfo);
} else {
- if ((!$viewhiddensections && !$section->visible) || (!$this->showemptysections && !array_key_exists($section->section, $modinfo->sections))) {
+ //Checking availability conditions
+ $si = new condition_info_section($section);
+ $section->is_available = $si->is_available($information, true, $USER->id); //if not available 'information' will tell why
+ if (!$section->is_available && $section->showavailability) {
+ $section->greyout = true;
+ } else {
+ $section->greyout = false;
+ }
+
+ if (!$section->is_available || ( (!$viewhiddensections && !$section->visible) || (!$this->showemptysections && !array_key_exists($section->section, $modinfo->sections)))) {
continue;
}
if ($namingfunctionexists) {
@@ -1444,12 +1456,13 @@ class global_navigation extends navigation_node {
$url = null;
$sectionnode = $coursenode->add($sectionname, $url, navigation_node::TYPE_SECTION, null, $section->id);
$sectionnode->nodetype = navigation_node::NODETYPE_BRANCH;
- $sectionnode->hidden = (!$section->visible);
+
+ $sectionnode->hidden = (!$section->visible || $section->greyout);
if ($this->page->context->contextlevel != CONTEXT_MODULE && ($sectionnode->isactive || ($activesection && $section->section == $activesection))) {
$sectionnode->force_open();
$this->load_section_activities($sectionnode, $section->section, $modinfo);
}
- $section->sectionnode = $sectionnode;
+ $section->sectionnode = $sectionnode;
$navigationsections[$sectionid] = $section;
}
}
@@ -1472,7 +1485,7 @@ class global_navigation extends navigation_node {
foreach ($modinfo->sections[$sectionnumber] as $cmid) {
$cm = $modinfo->cms[$cmid];
- if (!$cm->uservisible) {
+ if (!$cm->uservisible || $sectionnode->hidden) {
continue;
}
if ($cm->icon) {
diff --git a/local/section_availability/db/install.xml b/local/section_availability/db/install.xml
new file mode 100644
index 0000000..385dd55
--- /dev/null
+++ b/local/section_availability/db/install.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/local/section_availability/version.php b/local/section_availability/version.php
new file mode 100644
index 0000000..c28e94d
--- /dev/null
+++ b/local/section_availability/version.php
@@ -0,0 +1,5 @@
+version = 2011061600; // The (date) version of this plugin
+
+?>