MDL-68615 questions: fix fiendish default idnumber edge case
authorTim Hunt <T.J.Hunt@open.ac.uk>
Tue, 5 May 2020 14:43:57 +0000 (15:43 +0100)
committerTim Hunt <T.J.Hunt@open.ac.uk>
Tue, 5 May 2020 15:19:54 +0000 (16:19 +0100)
lib/questionlib.php
lib/tests/questionlib_test.php

index 8b95027..8f2c834 100644 (file)
@@ -2407,13 +2407,16 @@ function core_question_find_next_unused_idnumber(?string $oldidnumber, int $cate
             [$categoryid], '', 'idnumber, 1');
 
     // Find the next unused idnumber.
-    $newidnumber = $oldidnumber;
+    $numberbit = 'X' . $matches[0]; // Need a string here so PHP does not do '0001' + 1 = 2.
+    $stem = substr($oldidnumber, 0, -strlen($matches[0]));
     do {
+
         // If we have got to something9999, insert an extra digit before incrementing.
-        if (preg_match('~^(.*[^0-9])(9+)$~', $newidnumber, $matches)) {
-            $newidnumber = $matches[1] . '0' . $matches[2];
+        if (preg_match('~^(.*[^0-9])(9+)$~', $numberbit, $matches)) {
+            $numberbit = $matches[1] . '0' . $matches[2];
         }
-        $newidnumber++;
+        $numberbit++;
+        $newidnumber = $stem . substr($numberbit, 1);
     } while (isset($usedidnumbers[$newidnumber]));
 
     return (string) $newidnumber;
index 3142b26..2347fb6 100644 (file)
@@ -2155,6 +2155,10 @@ class core_questionlib_testcase extends advanced_testcase {
             ['id9', 'id10'],
             ['id009', 'id010'],
             ['id999', 'id1000'],
+            ['0', '1'],
+            ['-1', '-2'],
+            ['1.0E+29', '1.0E+30'], // Idnumbers are strings, not floats.
+            ['1.0E-29', '1.0E-30'], // By the way, this is not a sensible idnumber!
         ];
     }