diff --git a/application/controllers/api/frontend/v1/Stundenplan.php b/application/controllers/api/frontend/v1/Stundenplan.php index 373e5a9f9..116854930 100644 --- a/application/controllers/api/frontend/v1/Stundenplan.php +++ b/application/controllers/api/frontend/v1/Stundenplan.php @@ -127,129 +127,30 @@ class Stundenplan extends FHCAPI_Controller $start_date = $this->input->get('start_date', TRUE); $end_date = $this->input->get('end_date', TRUE); - $student_uid = getAuthUID(); - - // check if authUID is mitarbeiter - $is_mitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter($student_uid)); - if($is_mitarbeiter) - { - $this->terminateWithError("Not possible to look at the Student Calendar as a Mitarbeiter"); - } + $student_uid = getAuthUID(); if(is_null($student_uid)) { $this->terminateWithError("No UID"); } - // gets all studiensemester from the student from start_date to end_date - $semester_range = $this->StudiensemesterModel->getByDate($start_date,$end_date); - $semester_range = array_map( - function($sem) - { - return $sem->studiensemester_kurzbz; - }, - $this->getDataOrTerminateWithError($semester_range) - ); - - // if no studiensemester is found for the given timespan, get the nearest studiensemester - if(count($semester_range) == 0) + $is_mitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter($student_uid)); + if($is_mitarbeiter) { - $aktuelle_studiensemester = $this->StudiensemesterModel->getNearest(); - $aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester); - if (count($aktuelle_studiensemester) == 0) { - $this->terminateWithError("No aktuelles semester"); - } - $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; - // push aktuelles semester in active semester array - array_push($semester_range, $aktuelle_studiensemester); - + $this->terminateWithError("Not possible to look at the Student Calendar as a Mitarbeiter"); } - + $semester_range = $this->studienSemesterErmitteln($start_date,$end_date); + $this->sortStudienSemester($semester_range); - //semester des Studenten ermitteln - if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true) - { - // get next studiensemester - $next_studiensemester = $this->StudiensemesterModel->getNextFrom($semester_range[(count($semester_range)-1)]); - $next_studiensemester = $this->getDataOrTerminateWithError($next_studiensemester); - if(count($next_studiensemester) == 0) - { - $this->terminateWithError("No next semester"); - } - $next_studiensemester = current($next_studiensemester)->studiensemester_kurzbz; - //push next semester in active semester array - array_push($semester_range, $next_studiensemester); - $this->sortStudienSemester($semester_range); - - // get previous studiensemester - $previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($semester_range[0]); - $previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester); - if (count($previous_studiensemester) == 0) { - $this->terminateWithError("No previous semester"); - } - $previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz; - // push previous semester in active semester array - array_push($semester_range, $previous_studiensemester); - $this->sortStudienSemester($semester_range); - } - else - { - $nearest_studiensemester = $this->StudiensemesterModel->getNearestFrom($semester_range[(count($semester_range)-1)]); - $nearest_studiensemester = $this->getDataOrTerminateWithError($nearest_studiensemester); - if (count($nearest_studiensemester) == 0) { - $this->terminateWithError("No nearest semester"); - } - $nearest_studiensemester = current($nearest_studiensemester)->studiensemester_kurzbz; - // push nearest semester in active semester array - array_push($semester_range, $nearest_studiensemester); - $this->sortStudienSemester($semester_range); - - } - - + $this->applyLoadUeberSemesterHaelfte($semester_range); + // getting the gruppen_kurzbz of the student in the different studiensemester - $benutzer_gruppen = []; + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range); - foreach($semester_range as $semester) - { - // for each active semester query the benutzer_gruppen associated to the semester - $benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery(" - SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?",[$student_uid, $semester]); - $benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query); - $benutzer_gruppen[$semester] = array_map(function($item){ return "'".$item->gruppe_kurzbz. "'";}, $benutzer_query_result); - } - - $student_lehrverband = []; + // getting the student_lehrverbaende of the student in the different studiensemester + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range); - foreach($semester_range as $semester) - { - // for each active semester query the student_lehrverband associated to the semester - $lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery(" - SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); - $lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query); - $student_lehrverband[$semester] = array_map( - function ($item) - { - $result = new stdClass(); - $result->studiengang_kz = $item->studiengang_kz; - $result->semester = $item->semester; - $result->verband = $item->verband; - $result->gruppe = $item->gruppe; - return $result; - }, - $lehrverband_query_result); - - } - - $studienSemesterDateRanges=[]; - foreach($semester_range as $semester){ - $semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester); - $semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende)); - $studienSemesterDateRanges[$semester] = $semester_start_ende; - } - $semester_range = $studienSemesterDateRanges; - $stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($this->StundenplanModel->getStundenplanQuery($start_date, $end_date, $semester_range, $benutzer_gruppen, $student_lehrverband)); $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; @@ -391,4 +292,268 @@ class Stundenplan extends FHCAPI_Controller ); } + + + private function fetchBenutzerGruppenFromStudiensemester($semester_range){ + $student_uid = getAuthUID(); + $benutzer_gruppen = []; + // for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array + /* + [ + ['WS2023'] => [['gruppe1_SS2023','gruppe2_SS2023'],['gruppe1_WS2023','gruppe2_WS2023']], + ['SS2024'] => [['gruppe1_WS2023','gruppe2_WS2023'],['gruppe1_SS2024','gruppe2_SS2024']], + ['WS2024'] => [['gruppe1_SS2024','gruppe2_SS2024'],['gruppe1_WS2024','gruppe2_WS2024']], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $benutzer_gruppen[$semester_key] = []; + // each semester could have ajoint semesters that need to be checked + foreach($semester_array as $semester=>$semester_date_range) + { + // for each active semester query the benutzer_gruppen associated to the semester + $benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?",[$student_uid, $semester]); + $benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query); + array_push( + $benutzer_gruppen[$semester_key], + array_map( + function($item) + { + return "'".$item->gruppe_kurzbz. "'"; + }, + $benutzer_query_result + ) + ); + } + } + + // merge the gruppen of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => ['gruppe1_SS2023','gruppe2_SS2023','gruppe1_WS2023','gruppe2_WS2023'], + ['SS2024'] => ['gruppe1_WS2023','gruppe2_WS2023','gruppe1_SS2024','gruppe2_SS2024'], + ['WS2024'] => ['gruppe1_SS2024','gruppe2_SS2024','gruppe1_WS2024','gruppe2_WS2024'], + ] + */ + $benutzer_gruppen = array_map( + function($gruppe) + { + $merged_gruppe = []; + foreach($gruppe as $gruppen_array) + { + $merged_gruppe = array_merge($merged_gruppe, $gruppen_array); + } + return $merged_gruppe; + }, + $benutzer_gruppen + ); + + return $benutzer_gruppen; + } + + private function fetchStudentlehrverbandFromStudiensemester($semester_range){ + $student_uid = getAuthUID(); + $student_lehrverband = []; + // for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array + /* + [ + ['WS2023'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ] ], + ['SS2024'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ] ], + ['WS2024'] => [ [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ] ], + ] + */ + foreach($semester_range as $semester_key => $semester_array) + { + $student_lehrverband[$semester_key] = []; + foreach($semester_array as $semester=>$semester_date_range) + { + // for each active semester query the student_lehrverband associated to the semester + $lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery(" + SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]); + $lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query); + array_push($student_lehrverband[$semester_key], array_map( + function ($item) + { + $result = new stdClass(); + $result->studiengang_kz = $item->studiengang_kz; + $result->semester = $item->semester; + $result->verband = $item->verband; + $result->gruppe = $item->gruppe; + return $result; + }, + $lehrverband_query_result)); + } + } + + // merge the studentlehrverband of each studiensemester together for the original studiensemester + /* + [ + ['WS2023'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], + ['SS2024'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], + ['WS2024'] => [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ], + ] + */ + $student_lehrverband = array_map( + function($studentlehrverband) + { + $merged_studentlehrverband = []; + foreach($studentlehrverband as $studentlehrverband_array) + { + $merged_studentlehrverband = array_merge($merged_studentlehrverband, $studentlehrverband_array); + } + return $merged_studentlehrverband; + }, + $student_lehrverband + ); + + return $student_lehrverband; + } + + private function applyLoadUeberSemesterHaelfte(&$semester_range){ + /* + @var($semester_collection) + convert the array of studiensemester into an associative array with the studiensemester as the key + and the values of each key are the studiensemester needed for the query associated to that studiensemester + example: + + #INPUT: + ['WS2023','SS2024','WS2024'] + #OUTPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + */ + $semester_collection = []; + foreach($semester_range as $studiensemester) + { + $previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($studiensemester); + $previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester); + if (count($previous_studiensemester) == 0) { + $this->terminateWithError("No previous semester"); + } + $previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz; + $semester_collection[$studiensemester] = [$previous_studiensemester, $studiensemester]; + } + + /* + @var($studienSemesterDateRanges) + fetches for each studiensemester the start and end date, (SS) summer studiensemester are extended by 1 month to cover the summerbreak + based on the LVPLAN_LOAD_UEBER_SEMESTERHAELFTE constant it will load both the semester and the previous semester with the full date range + or the semester with the full date range and the previous semester with the half date range: + + #INPUT: + [ + 'WS2023' => ['SS2023','WS2023'] + 'SS2024' => ['WS2023','SS2024'] + 'WS2024' => ['SS2024','WS2024'] + ] + #OUTPUT: depends whether LVPLAN_LOAD_UEBER_SEMESTERHAELFTE is true or false + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == true + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + ~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == false + [ + "SS2024": [ + "WS2023": [ + "start"=> "2024-02-03", + "ende"=> "2024-05-17" + ], + "SS2024": [ + "start"=> "2024-02-03", + "ende"=> "2024-08-31" + ] + ] + ] + */ + $studienSemesterDateRanges=[]; + foreach($semester_collection as $semester_original => $semester_adjoint) + { + $semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original); + $semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende)); + + // initialize empty arrays to add key value pairs + $studienSemesterDateRanges[$semester_original] = []; + + // check if the studiensemester is a summer semester and add 1 month to bridge the school summer break + $match = null; + preg_match("/^(SS)([0-9]+)/",$semester_original,$match); + if(count($match) >0) + { + $one_month = new DateInterval('P1M'); + $one_day = DateInterval::createFromDateString('1 days'); + $summer_studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende); + $summer_studiensemester_end_date->add($one_month); + $summer_studiensemester_end_date->sub($one_day); + $semester_start_ende->ende = date_format($summer_studiensemester_end_date,'Y-m-d'); + } + if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true) + { + foreach($semester_adjoint as $adjoint) + { + $studienSemesterDateRanges[$semester_original][$adjoint]=$semester_start_ende; + } + } + else + { + //TODO: half of a DateInterval might not be correctly calculated + // calculate the half of the studiensemester + $studiensemester_start_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->start); + $studiensemester_end_date = DateTime::createFromFormat('Y-m-d',$semester_start_ende->ende); + $studiensemester_time_difference = $studiensemester_start_date->diff($studiensemester_end_date); + $half_dateNumber = ceil($studiensemester_time_difference->d/2)+ceil(($studiensemester_time_difference->m*30)/2); + $half_dateInterval = new DateInterval('P'.strval($half_dateNumber) .'D'); + $studiensemester_half = date_format($studiensemester_start_date->add($half_dateInterval),'Y-m-d'); + + $first_half = new stdClass(); + $first_half->start = $semester_start_ende->start; + $first_half->ende = $studiensemester_half; + + $studienSemesterDateRanges[$semester_original][$semester_adjoint[0]] = $first_half; + $studienSemesterDateRanges[$semester_original][$semester_adjoint[1]] = $semester_start_ende; + } + $semester_range = $studienSemesterDateRanges; + } + } + + private function studienSemesterErmitteln($start_date,$end_date){ + + // gets all studiensemester from the student from start_date to end_date + $semester_range = $this->StudiensemesterModel->getByDate($start_date,$end_date); + $semester_range = array_map( + function($sem) + { + return $sem->studiensemester_kurzbz; + }, + $this->getDataOrTerminateWithError($semester_range) + ); + + // if no studiensemester is found for the given timespan, get the nearest studiensemester + if(count($semester_range) == 0) + { + $aktuelle_studiensemester = $this->StudiensemesterModel->getNearest(); + $aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester); + if (count($aktuelle_studiensemester) == 0) { + $this->terminateWithError("No aktuelles semester"); + } + $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; + // push aktuelles semester in active semester array + array_push($semester_range, $aktuelle_studiensemester); + + } + return $semester_range; + } + } diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index 92d03b701..01d8dd792 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -220,12 +220,18 @@ class Stundenplan_model extends DB_Model $query .= " AND ( "; } - foreach($semester as $sem => $date_range) + foreach($semester as $sem => $semester_date_range) { - if(count($gruppen[$sem]) > 0) + + foreach($semester_date_range as $sem_date => $sem_date_range) { + // if there are not groups for the semester skip the iteration step + if(!array_key_exists($sem_date,$gruppen) || count($gruppen[$sem_date]) == 0) + { + continue; + } // converts the array of gruppen strings into a sql IN (_,_,_) chain - $query .="(sp.gruppe_kurzbz IN (" .implode(',',$gruppen[$sem]).") AND sp.datum BETWEEN ".$this->escape($date_range->start)." AND ".$this->escape($date_range->ende)." )"; + $query .="(sp.gruppe_kurzbz IN (" .implode(',',$gruppen[$sem_date]).") AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende)." )"; // adds the OR sql chain only if the $studentlehrverbaende array is not empty // DOES not include the sql OR if the $studentlehrverbaende are empty and it is the last gruppen element in the iteration @@ -233,29 +239,32 @@ class Stundenplan_model extends DB_Model { $query .="OR"; } + } - } + } - foreach($semester as $sem=>$date_range) + foreach($semester as $sem=>$semester_date_range) { - - if(count($studentlehrverbaende[$sem]) > 0) + foreach($semester_date_range as $sem_date => $sem_date_range) { - foreach($studentlehrverbaende[$sem] as $key=>$lehrverband) + if(!array_key_exists($sem_date,$studentlehrverbaende) || count($studentlehrverbaende[$sem_date]) == 0) + { + continue; + } + foreach($studentlehrverbaende[$sem_date] as $key=>$lehrverband) { // adds the OR sql chain only if its not the first element in the first semester of the $studentlehrverbaende array - if($lehrverband != $studentlehrverbaende[array_keys($semester)[0]][0]) + if($sem != array_keys($semester)[0] || $key != array_keys($semester)[0]) { $query .="OR"; } - $query .= "((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($date_range->start)." AND ".$this->escape($date_range->ende).")"; + $query .= "((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")"; // Eintraege fuer den ganzen Verband - $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($date_range->start)." AND ".$this->escape($date_range->ende).")"; + $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")"; // Eintraege fuer das ganze Semester - $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($date_range->start)." AND ".$this->escape($date_range->ende).") AND gruppe_kurzbz is null)"; + $query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).") AND gruppe_kurzbz is null)"; } - - } + } } // closes the AND sql chain only if it was opened previously diff --git a/vilesci/stammdaten/ampel_uebersicht.php b/vilesci/stammdaten/ampel_uebersicht.php index 1b85a4bbd..6304486fb 100644 --- a/vilesci/stammdaten/ampel_uebersicht.php +++ b/vilesci/stammdaten/ampel_uebersicht.php @@ -38,23 +38,45 @@ echo ' Ampel - + - - - - - - + + +'; + + + include('../../include/meta/jquery.php'); + include('../../include/meta/jquery-tablesorter.php'); + +echo '