MDL-46824 core_grades: Control when drop lowest/keep highest is allowed

Part of: MDL-46576
This commit is contained in:
Frederic Massart 2014-09-19 13:07:25 +08:00 committed by Adrian Greeve
parent dcfc196a0d
commit 4272386a7d

View File

@ -160,6 +160,12 @@ class grade_category extends grade_object {
*/
public $coefstring = null;
/**
* Static variable storing the result from {@link self::can_apply_limit_rules}.
* @var bool
*/
protected $canapplylimitrules;
/**
* Builds this category's path string based on its parents (if any) and its own id number.
* This is typically done just before inserting this object in the DB for the first time,
@ -645,7 +651,9 @@ class grade_category extends grade_object {
// limit and sort
$allvalues = $grade_values;
$this->apply_limit_rules($grade_values, $items);
if ($this->can_apply_limit_rules()) {
$this->apply_limit_rules($grade_values, $items);
}
$moredropped = array_diff($allvalues, $grade_values);
foreach ($moredropped as $drop => $unused) {
@ -1124,8 +1132,11 @@ class grade_category extends grade_object {
$maxes[$item->id] = $item->grademax; // 0 = nograde, 1 = first scale item, 2 = second scale item
}
}
// apply droplow and keephigh
$this->apply_limit_rules($maxes, $items);
if ($this->can_apply_limit_rules()) {
// Apply droplow and keephigh.
$this->apply_limit_rules($maxes, $items);
}
$max = array_sum($maxes);
// update db if anything changed
@ -1296,6 +1307,70 @@ class grade_category extends grade_object {
}
}
/**
* Returns whether or not we can apply the limit rules.
*
* There are cases where drop lowest or keep highest should not be used
* at all. This method will determine whether or not this logic can be
* applied considering the current setup of the category.
*
* @return bool
*/
public function can_apply_limit_rules() {
if ($this->canapplylimitrules !== null) {
return $this->canapplylimitrules;
}
// Set it to be supported by default.
$this->canapplylimitrules = true;
// Natural aggregation.
if ($this->aggregation == GRADE_AGGREGATE_SUM) {
$canapply = true;
// Check until one child breaks the rules.
$gradeitems = $this->get_children();
$validitems = 0;
$lastweight = null;
$lastmaxgrade = null;
foreach ($gradeitems as $gradeitem) {
$gi = $gradeitem['object'];
if ($gradeitem['type'] == 'category') {
// Sub categories are not allowed because they can have dynamic weights/maxgrades.
$canapply = false;
break;
}
if ($gi->aggregationcoef > 0) {
// Extra credit items are not allowed.
$canapply = false;
break;
}
if ($lastweight !== null && $lastweight != $gi->aggregationcoef2) {
// One of the weight differs from another item.
$canapply = false;
break;
}
if ($lastmaxgrade !== null && $lastmaxgrade != $gi->grademax) {
// One of the max grade differ from another item. This is not allowed for now
// because we could be end up with different max grade between users for this category.
$canapply = false;
break;
}
$lastweight = $gi->aggregationcoef2;
$lastmaxgrade = $gi->grademax;
}
$this->canapplylimitrules = $canapply;
}
return $this->canapplylimitrules;
}
/**
* Returns true if category uses extra credit of any kind
*