-
Bug
-
Resolution: Fixed
-
Minor
-
3.9.9, 3.10.6, 3.11.2, 4.0
-
MOODLE_310_STABLE, MOODLE_311_STABLE, MOODLE_39_STABLE, MOODLE_400_STABLE
-
MOODLE_310_STABLE, MOODLE_311_STABLE
-
MDL-72432-master
-
-
Easy
-
Group import from CSV can fail when the CSV file is in UTF-8 and is containing the Byte Order Mark (EF BB BF) at the beginning of the file.
Steps to reproduce:
- Create a test course (if the attached csv is used the course name should be "test course 01")
- Go to Course -> Users -> Groups
- Click Import Groups
- Choose grouptest.csv file (file is attached to the ticket) in the file picker. Alternatively, another csv file can be picked, but to test the correct BOM processing the csv file needs BOM header bytes.
- CSV delimiter should be comma (,) and Encoding should be UTF-8 (which is default)
- Click "Import"
- The error is as follows:
"groupname" is not a valid field name
Debug info:
Error code: invalidfieldname
Stack trace: * line 498 of /lib/setuplib.php: moodle_exception thrown
- line 103 of /group/import.php: call to print_error()
The logic of import.php trims spaces and quotes, but it does not take into account the BOM, which is neither space nor quote sequence. It just uses the variable $rawlines, which starts as "\EF\BB\BFgroupname,coursename":
$header = explode($csvimport::get_delimiter($delimiter), array_shift($rawlines));
|
Hence $header[0] is "\EF\BB\BFgroupname", which is incorrect and it does not pass the check causing the error.
The correct way of obtaining the header information would be to use the method get_columns() from csv_import_reader class. The method load_csv_content() in __ csv_import_reader class __ trims BOM in the first line allowing to process the headers in the right way.
The fix is very simple:
------------------------------- group/import.php -------------------------------index 58f405bd0cd..b50f880d738 100644 |
@@ -61,8 +61,6 @@ if ($importform->is_cancelled()) { |
$text = $importform->get_file_content('userfile'); |
$text = preg_replace('!\r\n?!', "\n", $text); |
|
- $rawlines = explode("\n", $text); |
-
|
require_once($CFG->libdir . '/csvlib.class.php'); |
$importid = csv_import_reader::get_new_iid('groupimport'); |
$csvimport = new csv_import_reader($importid, 'groupimport'); |
@@ -95,7 +93,9 @@ if ($importform->is_cancelled()) { |
);
|
|
// --- get header (field names) --- |
- $header = explode($csvimport::get_delimiter($delimiter), array_shift($rawlines));
|
+ // Using get_columns() ensures the Byte Order Mark is removed. |
+ $header = $csvimport->get_columns();
|
+
|
// check for valid field names |
foreach ($header as $i => $h) {
|
$h = trim($h); $header[$i] = $h; // remove whitespace |
|