Skip to content

Commit

Permalink
MDL-44070 Conditional availability enhancements (6): core changes
Browse files Browse the repository at this point in the history
Changes core code to use new API instead of the old one when
checking user access to activities and sections.

Includes changes to other libraries that are necessary after
adding the availability system and removing old conditional tables
etc.
  • Loading branch information
sammarshallou committed Apr 7, 2014
1 parent 6a60109 commit 8d1f33e
Show file tree
Hide file tree
Showing 14 changed files with 393 additions and 402 deletions.
4 changes: 2 additions & 2 deletions admin/settings/subsystems.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
new lang_string('configcompletiondefault', 'completion'), 1, $options));

$optionalsubsystems->add($checkbox = new admin_setting_configcheckbox('enableavailability',
new lang_string('enableavailability','condition'),
new lang_string('configenableavailability','condition'), 0));
new lang_string('enableavailability', 'availability'),
new lang_string('enableavailability_desc', 'availability'), 0));
$checkbox->set_affects_modinfo(true);

$optionalsubsystems->add(new admin_setting_configcheckbox('enableplagiarism', new lang_string('enableplagiarism','plagiarism'), new lang_string('configenableplagiarism','plagiarism'), 0));
Expand Down
10 changes: 4 additions & 6 deletions course/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,9 @@ public static function get_course_contents($courseid, $options = array()) {
//user that can view hidden module should know about the visibility
$module['visible'] = $cm->visible;

//availability date (also send to user who can see hidden module when the showavailabilyt is ON)
if ($canupdatecourse or ($CFG->enableavailability && $canviewhidden && $cm->showavailability)) {
$module['availablefrom'] = $cm->availablefrom;
$module['availableuntil'] = $cm->availableuntil;
// Availability date (also send to user who can see hidden module).
if ($CFG->enableavailability && ($canviewhidden || $canupdatecourse)) {
$module['availability'] = $cm->availability;
}

$baseurl = 'webservice/pluginfile.php';
Expand Down Expand Up @@ -223,8 +222,7 @@ public static function get_course_contents_returns() {
'modicon' => new external_value(PARAM_URL, 'activity icon url'),
'modname' => new external_value(PARAM_PLUGIN, 'activity module type'),
'modplural' => new external_value(PARAM_TEXT, 'activity module plural name'),
'availablefrom' => new external_value(PARAM_INT, 'module availability start date', VALUE_OPTIONAL),
'availableuntil' => new external_value(PARAM_INT, 'module availability en date', VALUE_OPTIONAL),
'availability' => new external_value(PARAM_RAW, 'module availability settings', VALUE_OPTIONAL),
'indent' => new external_value(PARAM_INT, 'number of identation in the site'),
'contents' => new external_multiple_structure(
new external_single_structure(
Expand Down
15 changes: 2 additions & 13 deletions course/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1056,16 +1056,8 @@ function get_array_of_activities($courseid) {
$rawmods[$seq]->completiongradeitemnumber;
$mod[$seq]->completionview = $rawmods[$seq]->completionview;
$mod[$seq]->completionexpected = $rawmods[$seq]->completionexpected;
$mod[$seq]->availablefrom = $rawmods[$seq]->availablefrom;
$mod[$seq]->availableuntil = $rawmods[$seq]->availableuntil;
$mod[$seq]->showavailability = $rawmods[$seq]->showavailability;
$mod[$seq]->showdescription = $rawmods[$seq]->showdescription;
if (!empty($CFG->enableavailability)) {
condition_info::fill_availability_conditions($rawmods[$seq]);
$mod[$seq]->conditionscompletion = $rawmods[$seq]->conditionscompletion;
$mod[$seq]->conditionsgrade = $rawmods[$seq]->conditionsgrade;
$mod[$seq]->conditionsfield = $rawmods[$seq]->conditionsfield;
}
$mod[$seq]->availability = $rawmods[$seq]->availability;

$modname = $mod[$seq]->mod;
$functionname = $modname."_get_coursemodule_info";
Expand Down Expand Up @@ -1139,8 +1131,7 @@ function get_array_of_activities($courseid) {
// 'empty'. This list corresponds to code in the cm_info constructor.
foreach (array('idnumber', 'groupmode', 'groupingid', 'groupmembersonly',
'indent', 'completion', 'extra', 'extraclasses', 'iconurl', 'onclick', 'content',
'icon', 'iconcomponent', 'customdata', 'showavailability', 'availablefrom',
'availableuntil', 'conditionscompletion', 'conditionsgrade',
'icon', 'iconcomponent', 'customdata', 'availability',
'completionview', 'completionexpected', 'score', 'showdescription')
as $property) {
if (property_exists($mod[$seq], $property) &&
Expand Down Expand Up @@ -1698,8 +1689,6 @@ function course_delete_module($cmid) {
// features are not turned on, in case they were turned on previously (these will be
// very quick on an empty table).
$DB->delete_records('course_modules_completion', array('coursemoduleid' => $cm->id));
$DB->delete_records('course_modules_availability', array('coursemoduleid'=> $cm->id));
$DB->delete_records('course_modules_avail_fields', array('coursemoduleid' => $cm->id));
$DB->delete_records('course_completion_criteria', array('moduleinstance' => $cm->id,
'criteriatype' => COMPLETION_CRITERIA_TYPE_ACTIVITY));

Expand Down
66 changes: 13 additions & 53 deletions course/tests/courselib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,10 @@ private function create_specific_module_test($modulename) {
$moduleinfo->completionexpected = time() + (7 * 24 * 3600);

// Conditional activity.
$moduleinfo->availablefrom = time();
$moduleinfo->availableuntil = time() + (7 * 24 * 3600);
$moduleinfo->showavailability = CONDITION_STUDENTVIEW_SHOW;
$moduleinfo->availability = '{"op":"&","showc":[true,true],"c":[' .
'{"type":"date","d":">=","t":' . time() . '},' .
'{"type":"date","d":"<","t":' . (time() + (7 * 24 * 3600)) . '}' .
']}';
$coursegradeitem = grade_item::fetch_course_item($moduleinfo->course); //the activity will become available only when the user reach some grade into the course itself.
$moduleinfo->conditiongradegroup = array(array('conditiongradeitemid' => $coursegradeitem->id, 'conditiongrademin' => 10, 'conditiongrademax' => 80));
$moduleinfo->conditionfieldgroup = array(array('conditionfield' => 'email', 'conditionfieldoperator' => OP_CONTAINS, 'conditionfieldvalue' => '@'));
Expand Down Expand Up @@ -280,9 +281,7 @@ private function create_specific_module_test($modulename) {
$this->assertEquals($moduleinfo->completionview, $dbcm->completionview);
$this->assertEquals($moduleinfo->completiongradeitemnumber, $dbcm->completiongradeitemnumber);
$this->assertEquals($moduleinfo->completionexpected, $dbcm->completionexpected);
$this->assertEquals($moduleinfo->availablefrom, $dbcm->availablefrom);
$this->assertEquals($moduleinfo->availableuntil, $dbcm->availableuntil);
$this->assertEquals($moduleinfo->showavailability, $dbcm->showavailability);
$this->assertEquals($moduleinfo->availability, $dbcm->availability);
$this->assertEquals($moduleinfo->showdescription, $dbcm->showdescription);
$this->assertEquals($moduleinfo->groupmode, $dbcm->groupmode);
$this->assertEquals($moduleinfo->cmidnumber, $dbcm->idnumber);
Expand All @@ -298,25 +297,6 @@ private function create_specific_module_test($modulename) {
$this->assertEquals($moduleinfo->intro, $dbmodinstance->intro);
$this->assertEquals($moduleinfo->introformat, $dbmodinstance->introformat);

// Common values when conditional activity is enabled.
foreach ($moduleinfo->conditionfieldgroup as $fieldgroup) {
$isfieldgroupsaved = $DB->count_records('course_modules_avail_fields', array('coursemoduleid' => $dbcm->id,
'userfield' => $fieldgroup['conditionfield'], 'operator' => $fieldgroup['conditionfieldoperator'],
'value' => $fieldgroup['conditionfieldvalue']));
$this->assertEquals(1, $isfieldgroupsaved);
}
foreach ($moduleinfo->conditiongradegroup as $gradegroup) {
$isgradegroupsaved = $DB->count_records('course_modules_availability', array('coursemoduleid' => $dbcm->id,
'grademin' => $gradegroup['conditiongrademin'], 'grademax' => $gradegroup['conditiongrademax'],
'gradeitemid' => $gradegroup['conditiongradeitemid']));
$this->assertEquals(1, $isgradegroupsaved);
}
foreach ($moduleinfo->conditioncompletiongroup as $completiongroup) {
$iscompletiongroupsaved = $DB->count_records('course_modules_availability', array('coursemoduleid' => $dbcm->id,
'sourcecmid' => $completiongroup['conditionsourcecmid'], 'requiredcompletion' => $completiongroup['conditionrequiredcompletion']));
$this->assertEquals(1, $iscompletiongroupsaved);
}

// Test specific to the module.
$modulerunasserts = $modulename.'_create_run_asserts';
$this->$modulerunasserts($moduleinfo, $dbmodinstance);
Expand Down Expand Up @@ -478,13 +458,14 @@ private function update_specific_module_test($modulename) {
$moduleinfo->completionunlocked = 1;

// Conditional activity.
$moduleinfo->availablefrom = time();
$moduleinfo->availableuntil = time() + (7 * 24 * 3600);
$moduleinfo->showavailability = CONDITION_STUDENTVIEW_SHOW;
$coursegradeitem = grade_item::fetch_course_item($moduleinfo->course); //the activity will become available only when the user reach some grade into the course itself.
$moduleinfo->conditiongradegroup = array(array('conditiongradeitemid' => $coursegradeitem->id, 'conditiongrademin' => 10, 'conditiongrademax' => 80));
$moduleinfo->conditionfieldgroup = array(array('conditionfield' => 'email', 'conditionfieldoperator' => OP_CONTAINS, 'conditionfieldvalue' => '@'));
$moduleinfo->conditioncompletiongroup = array(array('conditionsourcecmid' => $assigncm->id, 'conditionrequiredcompletion' => COMPLETION_COMPLETE)); // "conditionsourcecmid == 0" => none
$moduleinfo->availability = '{"op":"&","showc":[true,true],"c":[' .
'{"type":"date","d":">=","t":' . time() . '},' .
'{"type":"date","d":"<","t":' . (time() + (7 * 24 * 3600)) . '}' .
'{"type":"grade","id":' . $coursegradeitem->id . ',"min":10,"max":80},' .
'{"type":"profile","sf":"email","op":"contains","v":"@"},'.
'{"type":"completion","id":'. $assigncm->id . ',"e":' . COMPLETION_COMPLETE . '}' .
']}';

// Grading and Advanced grading.
require_once($CFG->dirroot . '/rating/lib.php');
Expand Down Expand Up @@ -533,9 +514,7 @@ private function update_specific_module_test($modulename) {
$this->assertEquals($moduleinfo->completionview, $dbcm->completionview);
$this->assertEquals($moduleinfo->completiongradeitemnumber, $dbcm->completiongradeitemnumber);
$this->assertEquals($moduleinfo->completionexpected, $dbcm->completionexpected);
$this->assertEquals($moduleinfo->availablefrom, $dbcm->availablefrom);
$this->assertEquals($moduleinfo->availableuntil, $dbcm->availableuntil);
$this->assertEquals($moduleinfo->showavailability, $dbcm->showavailability);
$this->assertEquals($moduleinfo->availability, $dbcm->availability);
$this->assertEquals($moduleinfo->showdescription, $dbcm->showdescription);
$this->assertEquals($moduleinfo->groupmode, $dbcm->groupmode);
$this->assertEquals($moduleinfo->cmidnumber, $dbcm->idnumber);
Expand All @@ -551,25 +530,6 @@ private function update_specific_module_test($modulename) {
$this->assertEquals($moduleinfo->intro, $dbmodinstance->intro);
$this->assertEquals($moduleinfo->introformat, $dbmodinstance->introformat);

// Common values when conditional activity is enabled.
foreach ($moduleinfo->conditionfieldgroup as $fieldgroup) {
$isfieldgroupsaved = $DB->count_records('course_modules_avail_fields', array('coursemoduleid' => $dbcm->id,
'userfield' => $fieldgroup['conditionfield'], 'operator' => $fieldgroup['conditionfieldoperator'],
'value' => $fieldgroup['conditionfieldvalue']));
$this->assertEquals(1, $isfieldgroupsaved);
}
foreach ($moduleinfo->conditiongradegroup as $gradegroup) {
$isgradegroupsaved = $DB->count_records('course_modules_availability', array('coursemoduleid' => $dbcm->id,
'grademin' => $gradegroup['conditiongrademin'], 'grademax' => $gradegroup['conditiongrademax'],
'gradeitemid' => $gradegroup['conditiongradeitemid']));
$this->assertEquals(1, $isgradegroupsaved);
}
foreach ($moduleinfo->conditioncompletiongroup as $completiongroup) {
$iscompletiongroupsaved = $DB->count_records('course_modules_availability', array('coursemoduleid' => $dbcm->id,
'sourcecmid' => $completiongroup['conditionsourcecmid'], 'requiredcompletion' => $completiongroup['conditionrequiredcompletion']));
$this->assertEquals(1, $iscompletiongroupsaved);
}

// Test specific to the module.
$modulerunasserts = $modulename.'_update_run_asserts';
$this->$modulerunasserts($moduleinfo, $dbmodinstance);
Expand Down
12 changes: 6 additions & 6 deletions grade/report/user/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,16 +360,16 @@ private function fill_table_recursive(&$element) {
($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
$hide = true;
} else if (!empty($grade_object->itemmodule) && !empty($grade_object->iteminstance)) {
// The grade object can be marked visible but still be hidden if...
// 1) "enablegroupmembersonly" is on and the activity is assigned to a grouping the user is not in.
// 2) the student cannot see the activity due to conditional access and its set to be hidden entirely.
// The grade object can be marked visible but still be hidden if
// the student cannot see the activity due to conditional access
// and it's set to be hidden entirely.
$instances = $this->gtree->modinfo->get_instances_of($grade_object->itemmodule);
if (!empty($instances[$grade_object->iteminstance])) {
$cm = $instances[$grade_object->iteminstance];
if (!$cm->uservisible) {
// Further checks are required to determine whether the activity is entirely hidden or just greyed out.
if ($cm->is_user_access_restricted_by_group() || $cm->is_user_access_restricted_by_conditional_access() ||
$cm->is_user_access_restricted_by_capability()) {
// If there is 'availableinfo' text then it is only greyed
// out and not entirely hidden.
if (!$cm->availableinfo) {
$hide = true;
}
}
Expand Down
21 changes: 11 additions & 10 deletions grade/tests/reportuserlib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,17 @@ public function test_inject_rowspans() {
}

// Conditional activity tests.
$DB->insert_record('course_modules_availability', (object)array(
'coursemoduleid'=>$forum1cm->id,
'gradeitemid' => 37,
'grademin' => 5.5
));

$cm = (object)array('id' => $forum1cm->id);
$test = new condition_info($cm, CONDITION_MISSING_EVERYTHING);
$fullcm = $test->get_full_course_module();

// Note: I have ported this test to the new conditional availability
// system, but it does not appear to actually test anything - in fact,
// if you remove the code that sets the condition, it still passes
// because it apparently is intended to have the same number of rows
// even when some are hidden. The same is true of the
// set_coursemodule_visible test above. I don't feel this is a very
// good test; somebody with more knowledge of this report might want to
// fix it to check that the row actually is being hidden.
$DB->set_field('course_modules', 'availability', '{"op":"|","show":false,"c":[' .
'{"type":"grade","min":5.5,"id":37}]}', array('id' => $forum1cm->id));
get_fast_modinfo($course->id, 0, true);
foreach ($users as $user) {

$this->setUser($user);
Expand Down
45 changes: 5 additions & 40 deletions lib/datalib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,11 @@ function get_all_instances_in_course($modulename, $course, $userid=NULL, $includ
* and the module's type (eg "forum") returns whether the object
* is visible or not, groupmembersonly visibility not tested
*
* NOTE: This does NOT take into account visibility to a particular user.
* To get visibility access for a specific user, use get_fast_modinfo, get a
* cm_info object from this, and check the ->uservisible property; or use
* the \core_availability\info_module::is_user_visible() static function.
*
* @global object
* @param $moduletype Name of the module eg 'forum'
Expand All @@ -1548,46 +1553,6 @@ function instance_is_visible($moduletype, $module) {
return true; // visible by default!
}

/**
* Determine whether a course module is visible within a course,
* this is different from instance_is_visible() - faster and visibility for user
*
* @global object
* @global object
* @uses DEBUG_DEVELOPER
* @uses CONTEXT_MODULE
* @uses CONDITION_MISSING_EXTRATABLE
* @param object $cm object
* @param int $userid empty means current user
* @return bool Success
*/
function coursemodule_visible_for_user($cm, $userid=0) {
global $USER,$CFG;

if (empty($cm->id)) {
debugging("Incorrect course module parameter!", DEBUG_DEVELOPER);
return false;
}
if (empty($userid)) {
$userid = $USER->id;
}
if (!$cm->visible and !has_capability('moodle/course:viewhiddenactivities', context_module::instance($cm->id), $userid)) {
return false;
}
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',
context_module::instance($cm->id), $userid)) {
return false;
}
}
return groups_course_module_visible($cm, $userid);
}




/// LOG FUNCTIONS /////////////////////////////////////////////////////

Expand Down
Loading

0 comments on commit 8d1f33e

Please sign in to comment.