diff --git a/grade/edit/letter/index.php b/grade/edit/letter/index.php index 19743672f9d..c0e468f8d73 100644 --- a/grade/edit/letter/index.php +++ b/grade/edit/letter/index.php @@ -137,7 +137,7 @@ if (!$edit) { } $letters = array(); - for($i=1; $i<$num+1; $i++) { + for ($i=1; $i < $num+1; $i++) { $gradelettername = 'gradeletter'.$i; $gradeboundaryname = 'gradeboundary'.$i; @@ -146,33 +146,54 @@ if (!$edit) { if ($letter == '') { continue; } + $boundary = floatval($data->$gradeboundaryname); + + if ($boundary < 0 || $boundary > 100) { + continue; // skip if out of range + } + // The keys need to be strings so floats are not truncated. - $letters[strval($data->$gradeboundaryname)] = $letter; + $letters[number_format($boundary, 5)] = $letter; } } - krsort($letters, SORT_NUMERIC); - $old_ids = array(); - if ($records = $DB->get_records('grade_letters', array('contextid' => $context->id), 'lowerboundary ASC', 'id')) { - $old_ids = array_keys($records); + $pool = array(); + if ($records = $DB->get_records('grade_letters', array('contextid' => $context->id), 'lowerboundary ASC')) { + foreach ($records as $r) { + // will re-use the lowerboundary to avoid duplicate during the update process + $pool[number_format($r->lowerboundary, 5)] = $r; + } } - foreach($letters as $boundary=>$letter) { + foreach ($letters as $boundary => $letter) { $record = new stdClass(); $record->letter = $letter; $record->lowerboundary = $boundary; $record->contextid = $context->id; - if ($old_id = array_pop($old_ids)) { - $record->id = $old_id; + // re-use the existing boundary to avoid key constraint + if (isset($pool[$boundary])) { + // skip if the letter has been assigned to the boundary already + if ($letter == $pool[$boundary]->letter) { + unset($pool[$boundary]); // take it out of the pool + } + else { + $record->id = $pool[$boundary]->id; + $DB->update_record('grade_letters', $record); + unset($pool[$boundary]); // remove the ID from the pool + } + } + else if ($candidate = array_pop($pool)) { + $record->id = $candidate->id; $DB->update_record('grade_letters', $record); } else { $DB->insert_record('grade_letters', $record); } } - foreach($old_ids as $old_id) { - $DB->delete_records('grade_letters', array('id' => $old_id)); + // delete the unused records + foreach($pool as $leftover) { + $DB->delete_records('grade_letters', array('id' => $leftover->id)); } redirect($returnurl);