Merge branch 'wip-MDL-28463-master' of git://github.com/marinaglancy/moodle

Conflicts:
	version.php
This commit is contained in:
Damyon Wiese 2013-11-01 21:31:57 +08:00
commit e9a20b4703
6 changed files with 117 additions and 111 deletions

View File

@ -46,6 +46,7 @@ $string['cachedef_coursemodinfo'] = 'Accumulated information about modules and s
$string['cachedef_databasemeta'] = 'Database meta information';
$string['cachedef_eventinvalidation'] = 'Event invalidation';
$string['cachedef_externalbadges'] = 'External badges for particular user';
$string['cachedef_gradecondition'] = 'User grades cached for evaluating conditional availability';
$string['cachedef_groupdata'] = 'Course group information';
$string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content';
$string['cachedef_langmenu'] = 'List of available languages';

View File

@ -1151,7 +1151,6 @@ abstract class condition_info_base {
*
* @global stdClass $USER
* @global moodle_database $DB
* @global stdClass $SESSION
* @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
@ -1161,71 +1160,73 @@ abstract class condition_info_base {
* 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->item->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;
global $USER, $DB;
if (!$userid) {
$userid = $USER->id;
}
$cache = cache::make('core', 'gradecondition');
if (($cachedgrades = $cache->get($userid)) === false) {
$cachedgrades = array();
}
if (!array_key_exists($gradeitemid, $cachedgrades)) {
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($userid, $this->item->course));
foreach ($rs as $record) {
$cachedgrades[$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, $cachedgrades)) {
$cachedgrades[$gradeitemid] = false;
}
} else {
// Just get current grade
$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;
}
$cachedgrades[$gradeitemid]=$score;
}
$cache->set($userid, $cachedgrades);
}
return $cachedgrades[$gradeitemid];
}
/**
* Called by grade code to inform the completion system when a grade has
* been changed. Grades can be used to determine condition for
* the course-module or section.
*
* Note that this function may be called twice for one changed grade object.
*
* @param grade_grade $grade
* @param bool $deleted
*/
public static function inform_grade_changed($grade, $deleted) {
cache::make('core', 'gradecondition')->delete($grade->userid);
}
/**
@ -1389,16 +1390,12 @@ abstract class condition_info_base {
}
/**
* For testing only. Wipes information cached in user session.
*
* @global stdClass $SESSION
* For testing only. Wipes information cached in cache.
* Replaced with {@link core_conditionlib_testcase::wipe_condition_cache()}
* @deprecated since 2.6
*/
static function wipe_session_cache() {
global $SESSION;
unset($SESSION->gradescorecache);
unset($SESSION->gradescorecacheuserid);
unset($SESSION->userfieldcache);
unset($SESSION->userfieldcacheuserid);
cache::make('core', 'gradecondition')->purge();
}
/**

View File

@ -205,4 +205,11 @@ $definitions = array(
'simplekeys' => true,
'simpledata' => true
),
// Used to cache user grades for conditional availability purposes.
'gradecondition' => array(
'mode' => cache_store::MODE_APPLICATION,
'staticacceleration' => true,
'staticaccelerationsize' => 2, // Should not be required for more than one user at a time.
'ttl' => 3600,
),
);

View File

@ -772,12 +772,7 @@ class grade_grade extends grade_object {
* @param bool $deleted True if grade was actually deleted
*/
function notify_changed($deleted) {
global $USER, $SESSION, $CFG,$COURSE, $DB;
// Grades may be cached in user session
if ($USER->id == $this->userid) {
unset($SESSION->gradescorecache[$this->itemid]);
}
global $CFG;
// Ignore during restore
// TODO There should be a proper way to determine when we are in restore
@ -787,6 +782,12 @@ class grade_grade extends grade_object {
return;
}
// Inform conditionlib since it may cache the grades for conditional availability of modules or sections.
if (!empty($CFG->enableavailability)) {
require_once($CFG->libdir.'/conditionlib.php');
condition_info_base::inform_grade_changed($this, $deleted);
}
require_once($CFG->libdir.'/completionlib.php');
// Bail out immediately if completion is not enabled for site (saves loading
@ -804,11 +805,7 @@ class grade_grade extends grade_object {
}
// Use $COURSE if available otherwise get it via item fields
if(!empty($COURSE) && $COURSE->id == $this->grade_item->courseid) {
$course = $COURSE;
} else {
$course = $DB->get_record('course', array('id'=>$this->grade_item->courseid));
}
$course = get_course($this->grade_item->courseid, false);
// Bail out if completion is not enabled for course
$completion = new completion_info($course);

View File

@ -44,6 +44,10 @@ class core_conditionlib_testcase extends advanced_testcase {
$this->setUser($user);
}
protected function wipe_condition_cache() {
cache::make('core', 'gradecondition')->purge();
}
public function test_constructor() {
global $DB;
$cm = new stdClass;
@ -480,7 +484,7 @@ class core_conditionlib_testcase extends advanced_testcase {
$ci = new condition_info((object)array('id'=>$cmid), CONDITION_MISSING_EVERYTHING);
$ci->add_completion_condition($oldid, COMPLETION_COMPLETE);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text, false));
$this->assertEquals(get_string('requires_completion_1', 'condition', 'xxx'), $text);
@ -488,23 +492,23 @@ class core_conditionlib_testcase extends advanced_testcase {
$completion = new completion_info($DB->get_record('course', array('id'=>$courseid)));
$completion->update_state($oldcm, COMPLETION_COMPLETE);
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
$this->assertFalse($ci->is_available($text, false, $USER->id+1));
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$completion = new completion_info($DB->get_record('course', array('id'=>$courseid)));
$completion->update_state($oldcm, COMPLETION_INCOMPLETE);
$this->assertFalse($ci->is_available($text));
$ci->wipe_conditions();
$ci->add_completion_condition($oldid, COMPLETION_INCOMPLETE);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
$this->assertTrue($ci->is_available($text, false, $USER->id+1));
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text, true));
// Grade.
@ -520,48 +524,48 @@ class core_conditionlib_testcase extends advanced_testcase {
// Fake it existing.
$DB->insert_record('grade_grades', (object)array(
'itemid'=>$gradeitemid, 'userid'=>$USER->id, 'finalgrade'=>3.78));
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text, true));
// Now require that user gets more than 3.78001.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3.78001, null, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_min', 'condition', 'frog'), $text);
// ...just on 3.78...
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3.78, null, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// ...less than 3.78.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, null, 3.78, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_max', 'condition', 'frog'), $text);
// ...less than 3.78001.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, null, 3.78001, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that includes it.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3, 4, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that doesn't include it.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 4, 5, true);
condition_info::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_range', 'condition', 'frog'), $text);
}
@ -630,7 +634,7 @@ class core_conditionlib_testcase extends advanced_testcase {
$ci = new condition_info_section((object)array('id' => $sectionid),
CONDITION_MISSING_EVERYTHING);
$ci->add_completion_condition($cmid, COMPLETION_COMPLETE);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
// Completion: Check.
$this->assertFalse($ci->is_available($text, false));
@ -639,13 +643,13 @@ class core_conditionlib_testcase extends advanced_testcase {
$completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
$completion->update_state($cm, COMPLETION_COMPLETE);
completion_info::wipe_session_cache();
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
$this->assertFalse($ci->is_available($text, false, $USER->id + 1));
// Completion: Uncheck.
completion_info::wipe_session_cache();
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$completion = new completion_info($DB->get_record('course', array('id' => $courseid)));
$completion->update_state($cm, COMPLETION_INCOMPLETE);
$this->assertFalse($ci->is_available($text));
@ -653,10 +657,10 @@ class core_conditionlib_testcase extends advanced_testcase {
// Completion: Incomplete condition.
$ci->wipe_conditions();
$ci->add_completion_condition($cmid, COMPLETION_INCOMPLETE);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
$this->assertTrue($ci->is_available($text, false, $USER->id + 1));
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text, true));
// Grade: Add a fake grade item.
@ -672,47 +676,47 @@ class core_conditionlib_testcase extends advanced_testcase {
// Grade: Fake it existing.
$DB->insert_record('grade_grades', (object)array(
'itemid' => $gradeitemid, 'userid' => $USER->id, 'finalgrade' => 3.78));
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text, true));
// Grade: Now require that user gets more than 3.78001.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3.78001, null, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_min', 'condition', 'frog'), $text);
// Grade: ...just on 3.78...
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3.78, null, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// Grade: ...less than 3.78.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, null, 3.78, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_max', 'condition', 'frog'), $text);
// Grade: ...less than 3.78001.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, null, 3.78001, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// Grade: ...in a range that includes it.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 3, 4, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertTrue($ci->is_available($text));
// Grade: ...in a range that doesn't include it.
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid, 4, 5, true);
condition_info_section::wipe_session_cache();
$this->wipe_condition_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_range', 'condition', 'frog'), $text);

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2013110100.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2013110100.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.