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
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);
|
|
?>
|