ptut-vhost/build/api/module/Excel.php

327 lines
12 KiB
PHP

<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 19/02/18
* Time: 21:31
*/
namespace api\module;
use database\core\Repo;
use database\core\Repo_i;
use error\core\Err;
use error\core\Error;
use PhpOffice\PhpSpreadsheet\Exception;
class Excel
{
private const startLineUE = 5;
private const startLineProf = 10;
public function post($args){
if(isset($_FILES["file"]["tmp_name"])){
//put everything in a try so we catch all PhpExcel exceptions and return a clean API Response
try{
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($_FILES["file"]["tmp_name"]);
$spreadsheet->setActiveSheetIndex(0);
$UESpreadsheet = $spreadsheet->getActiveSheet();
/*
* Setting Up state variables
*/
//current formation
$formation = "";
//current UE code
$UECode = "";
//current UE
$UE = [];
//array containing all the UEs
$allUE = [];
//array containing all the formations
$allFormations = [];
/*
* declare the lambda that will add finalized UE to the array
*/
$addEU = function() use (&$UECode,&$allUE,&$UE){
if($UECode != ""){
if(isset($allUE[$UECode])){
$counter = 1;
while(isset($allUE[$UECode.$counter])) $counter++;
$allUE[$UECode.$counter] = $UE;
}else{
$allUE[$UECode] = $UE;
}
$UE = [];
}
};
/*
* declaring the lambda tha twill extract the list of formation involved in the group
*/
$getFormations = function(?string $group) use (&$formation,&$allFormations) : array{
if(!$group) return [$formation];
//replace the generic "INFO" keyword by the actual formation
$group = str_replace("INFO",$formation,$group);
//split the string
$groups = explode("+",$group);
//trim the strings
$groups = array_map('trim', $groups);
//delete empty strings
$groups = array_filter($groups);
foreach ($groups as $group){
if(!isset($allFormations[$group])){
$allFormations[$group] = [
"name" => $group,
"internal" => strpos(strtolower($group),"info") !== false ? true : false
];
}
}
return $groups;
};
/*
* declaring the lambda that will compute the part of internal students in the course (used for stats purpose)
*/
$getInternalStudentPart = function(?string $group) use (&$formation, $getFormations) : float{
if(!$group) return 1.0;
$groups = $getFormations($group);
if(!in_array($formation,$groups)){
return 0.0;
}else{
return 1/count($groups);
}
};
$exitWithNullException = function(){
exit(json_encode(["error" => true, "message" => "NullCelException"]));
};
//starting the iteration
foreach($UESpreadsheet->getRowIterator() as $row){
//skip the first rows
if($row->getRowIndex() < Excel::startLineUE) continue;
$firstCellValue = ($UESpreadsheet->getCellByColumnAndRow(1,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$secondCellValue = ($UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
//if the first value is not null and the second is, this means we change formation and rest the UUCode
if($secondCellValue == "" and $firstCellValue != "") {$formation = $firstCellValue; $addEU(); $UECode = ""; continue; }
//if no UE is set yet, find it
if($UECode == "" and $firstCellValue != "") $UECode = $firstCellValue;
//if the line is empty this means we change UE
if($firstCellValue == "" and $secondCellValue == "") {$addEU(); $UECode = ""; continue;}
//now we have a formation, a UE and we are sure the line is not empty, let's fill up this bad boy
//if the required field is not set this means we are at the header of the UE
if(!isset($UE["required"])){
$UE["name"] = ($UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue();
$UE["required"] = ($UESpreadsheet->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$UE["TotalVH"] = ($UESpreadsheet->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue();
$UE["CourseVH"] = ($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["CourseGroup"] = ($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
$UE["TdVH"] = ($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["TdGroup"] = ($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
$UE["TpVH"] = ($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["TpGroup"] = ($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
continue;
}
//we have a new group! if the array is not set, initialize it
if(!isset($UE["groups"])) $UE["groups"] = [
"Course" => [],
"TD" => [],
"TP" => []
];
//compute Course
if (($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()){
$UE["groups"]["Course"][] = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(7,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
}
//compute TDs
if(($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()){
$UE["groups"]["TD"][] = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(10,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
}
//compute TPs
if(($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()){
$UE["groups"]["TP"][] = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(13,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
}
}
/*
* Now we compute the professor list to get the full name , the number of hour he must do and the category he is in
*/
$spreadsheet->setActiveSheetIndex(1);
$ProfSpreadshit = $spreadsheet->getActiveSheet();
//array containing all the professors
$allProf = [];
//current professor category
$currentCategory = "";
//category as represented in the excel (as a number)
$currentCategoryIndex = 0;
foreach($ProfSpreadshit->getRowIterator() as $row){
//skip the first lines
if($row->getRowIndex() < Excel::startLineProf) continue;
$firstCellValue = ($ProfSpreadshit->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$secondCellValue = ($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
//skip empty lines
if(!$firstCellValue and !$secondCellValue) continue;
//if the first cell contains something and not the second, it means that we change category
if($firstCellValue && !$secondCellValue){
$currentCategory = $firstCellValue;
$currentCategoryIndex++;
}
//if the line is valid
if(($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue() and ($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue()){
$allProf[($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue()] = [
"categoryLabel" => $currentCategory,
"categoryIndex" => $currentCategoryIndex,
"lastName" => explode(" ",($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue(),2)[1],
"firstName" => explode(" ",($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue(),2)[0],
"hoursToDo" => ($ProfSpreadshit->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0
];
}
}
/*
* adding data to the database
*/
//professors
foreach ($allProf as $initials => &$prof){
//create or update the professor category
Repo::request("category", "createOrUpdate", $prof["categoryIndex"], utf8_decode($prof["categoryLabel"]));
//create the professor, as some names are missing, we replace them by something else
if(!$prof["lastName"]) $prof["lastName"] = "missingLastName";
if(!$prof["firstName"]) $prof["firstName"] = "missingFirstName";
$prof["dbId"] = Repo::request("professor", "exists", utf8_decode($prof["lastName"]), utf8_decode($prof["firstName"]));
if(!$prof["dbId"]){
$prof["dbId"] = Repo::request("professor", "create", utf8_decode($prof["lastName"]), utf8_decode($prof["firstName"]), $prof["categoryIndex"], $prof["hoursToDo"], $initials);
}
}
//formation and retreive the databse IDs
foreach ($allFormations as &$form){
$form["dbId"] = Repo::request("formation","exists", utf8_decode($form["name"]));
if(!$form["dbId"]){
$form["dbId"] = Repo::request("formation", "create", utf8_decode($form["name"]), $form["internal"]);
}
}
//UEs and corresponding groups
foreach ($allUE as $codeUE => $UE){
Repo::request("ue","create", utf8_decode($codeUE),
utf8_decode($UE["name"]),
$UE["required"] == "OBL",
$UE["CourseVH"],
$UE["TdVH"],
$UE["TpVH"]);
if(isset($UE["groups"])){
foreach ($UE["groups"] as $type => $groups){
foreach ($groups as $group){
$formations = [];
foreach ($group["formations"] as $form){
if(isset($allFormations[$form]["dbId"])){
$formations[] = $allFormations[$form]["dbId"];
}
}
switch ($type){
case "Course":
Repo::request("cours","create", utf8_decode($codeUE),
$allProf[$group["professor"]]["dbId"],
$group["VH"],
$formations);
break;
case "TD":
Repo::request("td","create", utf8_decode($codeUE),
$allProf[$group["professor"]]["dbId"],
$group["VH"],
$formations);
break;
case "TP":
Repo::request("tp","create", utf8_decode($codeUE),
$allProf[$group["professor"]]["dbId"],
$group["VH"],
$formations);
break;
}
}
}
}
}
return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ];
}catch (Exception $e){
return [ 'error' => new Error(Err::UnknownError) ];
}
}else{
return [ 'error' => new Error(Err::UploadError) ];
}
}
}