diff --git a/student_auto_feed/config.php b/student_auto_feed/config.php index e93085b..a7a73aa 100644 --- a/student_auto_feed/config.php +++ b/student_auto_feed/config.php @@ -142,6 +142,7 @@ define('COLUMN_REGISTRATION', 7); //Student enrollment status define('COLUMN_SECTION', 10); //Section student is enrolled define('COLUMN_USER_ID', 5); //Student's computer systems ID +define('COLUMN_NUMERIC_ID', 6); //Alternate ID Number (e.g. campus ID number) define('COLUMN_FIRSTNAME', 2); //Student's First Name define('COLUMN_LASTNAME', 1); //Student's Last Name define('COLUMN_PREFERREDNAME', 3); //Student's Preferred Name diff --git a/student_auto_feed/submitty_student_auto_feed.php b/student_auto_feed/submitty_student_auto_feed.php index 31da456..be8d9a1 100755 --- a/student_auto_feed/submitty_student_auto_feed.php +++ b/student_auto_feed/submitty_student_auto_feed.php @@ -141,25 +141,38 @@ private function validate_csv($csv_data) { //Validate CSV $validate_num_fields = VALIDATE_NUM_FIELDS; - $validation_flag = true; + $validation_flag = true; //Set to false to invalidate the entire CSV file. + $rpi_found_non_empty_row = false; //RPI edge case flag. foreach($csv_data as $index => $csv_row) { - //Split each row by delim character so that individual fields are indexed. - //Trim any extraneous whitespaces from all rows and fields. - $row = array(); - foreach (explode(CSV_DELIM_CHAR, trim($csv_row)) as $i=>$field) { - $row[$i] = trim($field); - } + // 1) Trim CSV row. Do not trim CSV_DELIM_CHAR. + // 2) Convert CSV row to array. + // 3) Trim array fields. + $trim_str = " \t\n\r\0\x0B"; //$trim_str = space, tab, newline, carriage return, null byte, vertical tab + $trim_str = str_replace(CSV_DELIM_CHAR, "", $trim_str); //remove CSV_DELIM_CHAR from $trim_str + $row = array_map('trim', explode(CSV_DELIM_CHAR, trim($csv_row, $trim_str))); //BEGIN VALIDATION //Invalidate any row that doesn't have requisite number of fields. Do this, first. //Invalidation will disqualify the data file to protect DB data integrity. $num_fields = count($row); if ($num_fields !== $validate_num_fields) { - $this->log_it("Row {$index} has {$num_fields} columns. {$validate_num_fields} expected."); + $this->log_it("Row {$index} has {$num_fields} columns. {$validate_num_fields} expected. CSV disqualified."); $validation_flag = false; continue; + } else if (empty(array_filter($row, function($field) { return !empty($field); }))) { + if (!$rpi_found_non_empty_row) { + // RPI edge case to skip a correctly sized row of all empty fields — at the top of a data file, before proper data is read — without invalidating the whole data file. + $this->log_it("Row {$index} is correct size ({$validate_num_fields}), but all columns are empty — at top of CSV. Ignoring row."); + continue; + } else { + // Correctly sized empty row below data row(s) — invalidate data file. + $this->log_it("Row {$index} is correct size ({$validate_num_fields}), but all columns are empty — below a non-empty data row. CSV disqualified."); + $validation_flag = false; + continue; + } } + $rpi_found_non_empty_row = true; $course = strtolower($row[COLUMN_COURSE_PREFIX]) . $row[COLUMN_COURSE_NUMBER]; // Remove any leading zeroes from "integer" registration sections. $section = (ctype_digit($row[COLUMN_SECTION])) ? ltrim($row[COLUMN_SECTION], "0") : $row[COLUMN_SECTION]; @@ -222,6 +235,7 @@ private function validate_csv($csv_data) { //Validation passed. Include row in data set. self::$data['users'][] = array('user_id' => $row[COLUMN_USER_ID], + 'user_numeric_id' => $row[COLUMN_NUMERIC_ID], 'user_firstname' => $row[COLUMN_FIRSTNAME], 'user_preferredname' => $row[COLUMN_PREFERREDNAME], 'user_lastname' => $row[COLUMN_LASTNAME], @@ -451,6 +465,7 @@ private function upsert_psql() { $sql['users']['temp_table'] = <<