Skip to content
Permalink
Browse files

MDL-47322 Availability: empty availability should be saved as null

As part of the unit test modifications for this change, I added the get_json
function to the availability conditions that didn't have it. (This is a function
for use in unit tests.)
  • Loading branch information...
sammarshallou committed Sep 18, 2014
1 parent d07b030 commit 06c060382517a22140e01145a56d8c7f97b65f3b
@@ -621,6 +621,15 @@ public function save() {
return $result;
}
/**
* Checks whether this tree is empty (contains no children).
*
* @return boolean True if empty
*/
public function is_empty() {
return count($this->children) === 0;
}
/**
* Recursively gets all children of a particular class (you can use a base
* class to get all conditions, or a specific class).
@@ -74,6 +74,21 @@ public function save() {
'cm' => $this->cmid, 'e' => $this->expectedcompletion);
}
/**
* Returns a JSON object which corresponds to a condition of this type.
*
* Intended for unit testing, as normally the JSON values are constructed
* by JavaScript code.
*
* @param int $cmid Course-module id of other activity
* @param int $expectedcompletion Expected completion value (COMPLETION_xx)
* @return stdClass Object representing condition
*/
public static function get_json($cmid, $expectedcompletion) {
return (object)array('type' => 'completion', 'cm' => (int)$cmid,
'e' => (int)$expectedcompletion);
}
public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
$modinfo = $info->get_modinfo();
$completion = new \completion_info($modinfo->get_course());
@@ -77,6 +77,20 @@ public function save() {
'd' => $this->direction, 't' => $this->time);
}
/**
* Returns a JSON object which corresponds to a condition of this type.
*
* Intended for unit testing, as normally the JSON values are constructed
* by JavaScript code.
*
* @param string $direction DIRECTION_xx constant
* @param int $time Time in epoch seconds
* @return stdClass Object representing condition
*/
public static function get_json($direction, $time) {
return (object)array('type' => 'date', 'd' => $direction, 't' => (int)$time);
}
public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
return $this->is_available_for_all($not);
}
@@ -85,6 +85,28 @@ public function save() {
return $result;
}
/**
* Returns a JSON object which corresponds to a condition of this type.
*
* Intended for unit testing, as normally the JSON values are constructed
* by JavaScript code.
*
* @param int $gradeitemid Grade item id
* @param number|null $min Min grade (or null if no min)
* @param number|null $max Max grade (or null if no max)
* @return stdClass Object representing condition
*/
public static function get_json($gradeitemid, $min = null, $max = null) {
$result = (object)array('type' => 'grade', 'id' => (int)$gradeitemid);
if (!is_null($min)) {
$result->min = $min;
}
if (!is_null($max)) {
$result->max = $max;
}
return $result;
}
public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
$course = $info->get_course();
$score = $this->get_cached_grade_score($this->gradeitemid, $course->id, $grabthelot, $userid);
@@ -142,6 +142,39 @@ public function save() {
return $result;
}
/**
* Returns a JSON object which corresponds to a condition of this type.
*
* Intended for unit testing, as normally the JSON values are constructed
* by JavaScript code.
*
* @param bool $customfield True if this is a custom field
* @param string $fieldname Field name
* @param string $operator Operator name (OP_xx constant)
* @param string|null $value Value (not required for some operator types)
* @return stdClass Object representing condition
*/
public static function get_json($customfield, $fieldname, $operator, $value = null) {
$result = (object)array('type' => 'profile', 'op' => $operator);
if ($customfield) {
$result->cf = $fieldname;
} else {
$result->sf = $fieldname;
}
switch ($operator) {
case self::OP_IS_EMPTY:
case self::OP_IS_NOT_EMPTY:
break;
default:
if (is_null($value)) {
throw new \coding_exception('Operator requires value');
}
$result->v = $value;
break;
}
return $result;
}
public function is_available($not, \core_availability\info $info, $grabthelot, $userid) {
$uservalue = $this->get_cached_user_profile_field($userid);
$allow = self::is_field_condition_met($this->operator, $uservalue, $this->value);
@@ -489,6 +489,21 @@ public function test_get_full_information() {
$tree->get_full_information($info));
}
/**
* Tests the is_empty() function.
*/
public function test_is_empty() {
// Tree with nothing in should be empty.
$structure = tree::get_root_json(array(), tree::OP_OR);
$tree = new tree($structure);
$this->assertTrue($tree->is_empty());
// Tree with something in is not empty.
$structure = tree::get_root_json(array(self::mock(array('m' => '1'))), tree::OP_OR);
$tree = new tree($structure);
$this->assertFalse($tree->is_empty());
}
/**
* Tests the get_all_children() function.
*/
@@ -85,6 +85,15 @@ function add_moduleinfo($moduleinfo, $course, $mform = null) {
} else if (property_exists($moduleinfo, 'availability')) {
$newcm->availability = $moduleinfo->availability;
}
// If there is any availability data, verify it.
if ($newcm->availability) {
$tree = new \core_availability\tree(json_decode($newcm->availability));
// Save time and database space by setting null if the only data
// is an empty tree.
if ($tree->is_empty()) {
$newcm->availability = null;
}
}
}
if (isset($moduleinfo->showdescription)) {
$newcm->showdescription = $moduleinfo->showdescription;
@@ -494,6 +503,15 @@ function update_moduleinfo($cm, $moduleinfo, $course, $mform = null) {
} else if (property_exists($moduleinfo, 'availability')) {
$cm->availability = $moduleinfo->availability;
}
// If there is any availability data, verify it.
if ($cm->availability) {
$tree = new \core_availability\tree(json_decode($cm->availability));
// Save time and database space by setting null if the only data
// is an empty tree.
if ($tree->is_empty()) {
$cm->availability = null;
}
}
}
if (isset($moduleinfo->showdescription)) {
$cm->showdescription = $moduleinfo->showdescription;
@@ -457,13 +457,12 @@ private function update_specific_module_test($modulename) {
// Conditional activity.
$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->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 . '}' .
']}';
$moduleinfo->availability = json_encode(\core_availability\tree::get_root_json(
array(\availability_date\condition::get_json('>=', time()),
\availability_date\condition::get_json('<', time() + (7 * 24 * 3600)),
\availability_grade\condition::get_json($coursegradeitem->id, 10, 80),
\availability_profile\condition::get_json(false, 'email', 'contains', '@'),
\availability_completion\condition::get_json($assigncm->id, COMPLETION_COMPLETE)), '&'));
// Grading and Advanced grading.
require_once($CFG->dirroot . '/rating/lib.php');
@@ -2509,4 +2508,43 @@ public function test_duplicate_module() {
$this->assertEquals($value, $newcm->$prop);
}
}
/**
* Tests that when creating or updating a module, if the availability settings
* are present but set to an empty tree, availability is set to null in
* database.
*/
public function test_empty_availability_settings() {
global $DB;
$this->setAdminUser();
$this->resetAfterTest();
// Enable availability.
set_config('enableavailability', 1);
// Test add.
$emptyavailability = json_encode(\core_availability\tree::get_root_json(array()));
$course = self::getDataGenerator()->create_course();
$label = self::getDataGenerator()->create_module('label', array(
'course' => $course, 'availability' => $emptyavailability));
$this->assertNull($DB->get_field('course_modules', 'availability',
array('id' => $label->cmid)));
// Test update.
$formdata = $DB->get_record('course_modules', array('id' => $label->cmid));
unset($formdata->availability);
$formdata->availabilityconditionsjson = $emptyavailability;
$formdata->modulename = 'label';
$formdata->coursemodule = $label->cmid;
$draftid = 0;
file_prepare_draft_area($draftid, context_module::instance($label->cmid)->id,
'mod_label', 'intro', 0);
$formdata->introeditor = array(
'itemid' => $draftid,
'text' => '<p>Yo</p>',
'format' => FORMAT_HTML);
update_module($formdata);
$this->assertNull($DB->get_field('course_modules', 'availability',
array('id' => $label->cmid)));
}
}

0 comments on commit 06c0603

Please sign in to comment.
You can’t perform that action at this time.