This is based on Moodle 1.9.15 function fix_course_sortorder($categoryid=0, $n=0, $safe=0, $depth=0, $path='') { ... if ($count && ( $safe || $hasgap || $mustshift ) ) { // special, optimized case where all we need is to shift if ( $mustshift && !$safe && !$hasgap) { $shift = $n + $catgap - $min; ------ => // changed: The case "$shift < $count" is new. $mustshift is set, if // "$min < $n-$tolerance || $min > $n+$tolerance+$catgap", e.g. if a sortorder value ist too big // or too small. The original code increased the value in both cases, what is not helpful for too // big sortorder values. And with the next call auf fix_course_sortorder the same procedure starts again ... if ($shift < 0) { $shift = 0 - $shift; $sqltext = "UPDATE {$CFG->prefix}course SET sortorder=sortorder-$shift WHERE category=$categoryid"; execute_sql($sqltext, 0); // setting the negative shift-value "directly" doesn't work (for our database, Oracle?) } elseif ($shift < $count) { $shift = $count + $catgap; execute_sql("UPDATE {$CFG->prefix}course SET sortorder=sortorder+$shift WHERE category=$categoryid", 0); } else { execute_sql("UPDATE {$CFG->prefix}course SET sortorder=sortorder+$shift WHERE category=$categoryid", 0); } ------ /* original code start if ($shift < $count) { $shift = $count + $catgap; } execute_sql("UPDATE {$CFG->prefix}course SET sortorder=sortorder+$shift WHERE category=$categoryid", 0); original code end */ $n = $n + $catgap + $count; } else { // do it slowly $n = $n + $catgap; // if the new sequence overlaps the current sequence, lack of transactions // will stop us -- shift things aside for a moment... if ($safe || ($n >= $min && $n+$count+1 < $min && $CFG->dbfamily==='mysql')) { => // comment: The second part can never get true. $count is always > 0, so we have something like // xn here. Don't know about the consequences, we don't use mysql. $shift = $max + $n + 1000; => // comment: $shift can get up to 2x$max. The next command uses $shift to set new sortorder // values. Later (in the following foreach-statement) the values are set "back", but that sometimes // doesn't work (details later), e.g. the sortorder-values remain on $shift + x ... execute_sql("UPDATE {$CFG->prefix}course SET sortorder=sortorder+$shift WHERE category=$categoryid", 0); } $courses = get_courses($categoryid, 'c.sortorder ASC', 'c.id,c.sortorder'); begin_sql(); $tx = true; // transaction sanity => // comment: If called in safe-mode, the set_field command in the folowing foreach-loop // hangs up. When using execute_sql, it works. Maybe a problem with our database (Oracle) and // transactions? foreach ($courses as $course) { if ($tx && $course->sortorder != $n ) { // save db traffic // Original-Code start // $tx = $tx && set_field('course', 'sortorder', $n, // 'id', $course->id); // Original-Code end ------ => $sqltxt = "update m_course set sortorder=$n where id=$course->id"; if ($safe) { // $tx1 = set_field('course', 'sortorder', $n, 'id', $course->id); $tx1 = execute_sql($sqltxt, false); } else { $tx1 = set_field('course', 'sortorder', $n, 'id', $course->id); } $tx = $tx && $tx1; ------ } $n++; } if ($tx) { commit_sql(); } else { rollback_sql(); if (!$safe) { // if we failed when called with !safe, try // to recover calling self with safe=true return fix_course_sortorder($categoryid, $n, true, $depth, $path); } } } } ... }