You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
7.5 KiB
PHP

<?php
/*
* This script takes two files, an IServ user export CSV and a DiViS student <> parents CSV
* and maps the parents to the IServ students, creating a third CSV file that can be imported
* into the IServ Elternverwaltung module.
*
* The IServ user export CSV is expected to have the following columns:
* Account;Vorname;Nachname;Status;"Erstellt am";"Erstellt von";"Interne ID";Benutzertyp;Import-ID;Klasse/Information;E-Mail-Adresse;Gruppen
*
* The student <> parents mapped CSV from DiViS should have the following columns:
* "Schüler Vorname","Schüler Nachname","Eltern 1 Vorname","Eltern 1 Nachname","Eltern 2 Vorname","Eltern 2 Nachname"
*
* The CSV exported by this script will have the following columns:
* Nachname;Vorname;Kind-ID;Klasse
*
* Status messages, information and errors are always written to STDERR, while the generated CSV
* will be exported to STDOUT, meaning you can redirect the STDOUT output of this script to a file
* to export the CSV and still be able to read any informational messages:
* $ php ./IServ_Elternimport_Divis.php iserv-user-export.csv divis-parents-export.csv > Parents_Import.csv
*/
define ("MIN_NAME_MATCHING_PERCENTAGE", 85);
define ("WRITE_TO_CONSOLE", true);
define ("IS_CLI", (php_sapi_name() == "cli"));
/**
* Writes text to the STDERR stream when running from the command line.
*
* @param string $text The text to write to console
* @return void
*/
function console_write ($text) {
global $argv;
if (IS_CLI && WRITE_TO_CONSOLE) {
fwrite (STDERR, $text . PHP_EOL);
}
}
/**
* Turns the first and last name of a student into a single string
* used to identify the student in the students array.
*
* @param string $firstname First name of the student
* @param string $lastname Last name of the student
* @return string Combined and lower-cased names of the student
*/
function hash_student ($firstname, $lastname) {
return strtolower($firstname) . "_" . strtolower($lastname);
}
/**
* Tries the parent(s) of a student by their first and last name
* in the DiViS student <> parents mapped CSV.
*
* @param string $firstname First name of the student
* @param string $lastname Last name of the student
* @return string|null Array of parents first and last names,
* or null if no matching data was found.
*/
function find_parent_by_student ($firstname, $lastname) {
global $divis_parents;
$student_hash = hash_student ($firstname, $lastname);
$best_match = [ "match_perc" => 0 ];
$perc = 0;
console_write ("INFO: Searching parent(s) for '{$firstname} {$lastname}' ({$student_hash})");
foreach ($divis_parents as $hash => $parent) {
similar_text ($student_hash, $hash, $perc);
// If match is bigger or equal to 85% and this match is higher
// ranked than the last, make this the current best match
if (
$perc >= MIN_NAME_MATCHING_PERCENTAGE &&
$best_match["match_perc"] < $perc
) {
console_write ("INFO: New best match '{$hash}' at {$perc}%");
$best_match = [
"match_perc" => $perc,
"student_hash" => $student_hash,
"parent_data" => $parent
];
}
}
if ($best_match["match_perc"] == 0) {
console_write ("WARN: Could not find parent for '{$firstname} {$lastname}'!");
return null;
}
$parent1_firstname = $best_match['parent_data']['parent1_firstname'];
$parent1_lastname = $best_match['parent_data']['parent1_lastname'];
$parent2_firstname = $best_match['parent_data']['parent2_firstname'];
$parent2_lastname = $best_match['parent_data']['parent2_lastname'];
console_write ("INFO: Found parent(s):");
console_write ("INFO: First Parent: {$parent1_firstname} {$parent1_lastname}");
console_write ("INFO: Second Parent: {$parent2_firstname} {$parent2_lastname}");
return [
"parent1" => [
"firstname" => $parent1_firstname,
"lastname" => $parent1_lastname
],
"parent2" => [
"firstname" => $parent2_firstname,
"lastname" => $parent2_lastname
]
];
}
// Test if the two required input files have been specified
if (isset ($argc) && $argc == 3) {
$iserv_infile = $argv[1];
$divis_infile = $argv[2];
if (! is_file ($iserv_infile)) {
console_write ("CRIT: The IServ CSV file specified is not a file or does not exist.");
exit (1);
}
if (! is_file ($divis_infile)) {
console_write ("CRIT: The DiViS CSV file specified is not a file or does not exist.");
exit (1);
}
} else {
console_write ("Usage: ");
console_write (" {$argv[0]} <iserv-user-export.csv> <divis-parents-export.csv>");
console_write ("");
exit (1);
}
// Read DiViS student <> parents mapped CSV to an array
$parents_csv_fd = fopen ($divis_infile, "r");
$divis_parents = [];
while ($parent = fgetcsv ($parents_csv_fd)) {
$student_firstname = $parent[0];
$student_lastname = $parent[1];
$student_hash = hash_student ($student_firstname, $student_lastname);
$divis_parents[$student_hash] = [
"student_firstname" => $student_firstname,
"student_lastname" => $student_lastname,
"parent1_firstname" => $parent[2],
"parent1_lastname" => $parent[3],
"parent2_firstname" => $parent[4],
"parent2_lastname" => $parent[5]
];
}
fclose ($parents_csv_fd);
// Iterate through all students in the IServ student export CSV
$students_csv_fd = fopen ($iserv_infile, "r");
$parents_to_export = [];
$students_without_parents = [];
fgets ($students_csv_fd); // Skip header in the CSV file
while ($student = fgetcsv ($students_csv_fd, null, ";")) {
// Skip non-student users
if ($student[7] !== "Schüler") continue;
$student_firstname = $student[1];
$student_lastname = $student[2];
$student_userid = $student[8];
$student_class = strtolower ($student[9]);
$student_class = "klasse." . str_replace (" ", ".", $student_class);
$parents = find_parent_by_student ($student_firstname, $student_lastname);
if ($parents == null) {
$students_without_parents[] = $student;
} else {
if ($parents["parent1"]["firstname"] && $parents["parent1"]["lastname"]) {
$parents_to_export[] = [
$parents["parent1"]["firstname"],
$parents["parent1"]["lastname"],
$student_userid,
$student_class
];
} else {
console_write ("WARN: Parent 1 dataset non-existant for student '{$student_firstname} {$student_lastname}'");
}
if ($parents["parent2"]["firstname"] && $parents["parent2"]["lastname"]) {
$parents_to_export[] = [
$parents["parent2"]["firstname"],
$parents["parent2"]["lastname"],
$student_userid,
$student_class
];
} else {
console_write ("WARN: Parent 2 dataset non-existant for student '{$student_firstname} {$student_lastname}'");
}
}
console_write ("");
}
fclose ($students_csv_fd);
// Iterate through each exportable parent and convert them to a CSV line
if (IS_CLI) {
$out_fd = STDOUT;
} else {
$out_fd = fopen ("php://output", "w");
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="Elternimport.csv";');
}
foreach ($parents_to_export as $parent) {
fputcsv($out_fd, $parent, ";");
}
fclose ($out_fd);
?>