diff options
| author | Peter Thienel <thienel@data-quest.de> | 2025-06-26 16:44:58 +0000 |
|---|---|---|
| committer | David Siegfried <david.siegfried@uni-vechta.de> | 2025-06-26 16:44:58 +0000 |
| commit | 6f7299342e86431a2ebd3a6197a985d1653b1dd2 (patch) | |
| tree | cc52bc96e0cad1ca0c0a33c4dcb048746db4ff83 | |
| parent | 176cf83d651b28f1d19895af375cef66292624ef (diff) | |
Resolve "Erweiterung der Modulverwaltung um Studiengangsspezifische Informationen"
Closes #5383
Merge request studip/studip!4051
39 files changed, 1024 insertions, 393 deletions
diff --git a/app/controllers/admin/datafields.php b/app/controllers/admin/datafields.php index 6188a02..2ec8762 100644 --- a/app/controllers/admin/datafields.php +++ b/app/controllers/admin/datafields.php @@ -59,15 +59,17 @@ class Admin_DatafieldsController extends AuthenticatedController ]; } else { $this->datafields_list = [ - 'sem' => DataField::getDataFields('sem'), - 'inst' => DataField::getDataFields('inst'), - 'user' => DataField::getDataFields('user'), - 'userinstrole' => DataField::getDataFields('userinstrole'), - 'usersemdata' => DataField::getDataFields('usersemdata'), - 'roleinstdata' => DataField::getDataFields('roleinstdata'), - 'moduldeskriptor' => DataField::getDataFields('moduldeskriptor'), - 'modulteildeskriptor' => DataField::getDataFields('modulteildeskriptor'), - 'studycourse' => DataField::getDataFields('studycourse'), + 'sem' => DataField::getDataFields('sem'), + 'inst' => DataField::getDataFields('inst'), + 'user' => DataField::getDataFields('user'), + 'userinstrole' => DataField::getDataFields('userinstrole'), + 'usersemdata' => DataField::getDataFields('usersemdata'), + 'roleinstdata' => DataField::getDataFields('roleinstdata'), + 'moduldeskriptor' => DataField::getDataFields('moduldeskriptor'), + 'modulteildeskriptor' => DataField::getDataFields('modulteildeskriptor'), + 'studycourse' => DataField::getDataFields('studycourse'), + 'stgteilabschnittmodul' => DataField::getDataFields('stgteilabschnittmodul'), + 'modulteilstgteilabschnitt' => DataField::getDataFields('modulteilstgteilabschnitt'), ]; } @@ -102,7 +104,10 @@ class Admin_DatafieldsController extends AuthenticatedController $object_class = implode(',', Request::getArray('object_class')); $datafield->object_class = (trim($object_class) && $object_class != 'NULL') ? $object_class : null; } elseif ($datafield->object_type === 'studycourse') { - $datafield->object_class = trim(Request::option('object_class', 'all_settings')); + $datafield->object_class = trim(Request::option('object_class', 'all_settings')); + } elseif ($datafield->object_type === 'stgteilabschnittmodul' + || $datafield->object_type === 'modulteilstgteilabschnitt') { + $datafield->object_class = Request::option('object_class'); } else { $datafield->object_class = array_sum(Request::intArray('object_class')) ?: null; } @@ -153,7 +158,12 @@ class Admin_DatafieldsController extends AuthenticatedController if ($type === 'moduldeskriptor' || $type === 'modulteildeskriptor') { $object_class = implode(',', Request::getArray('object_class')); $datafield->object_class = (trim($object_class) && $object_class != 'NULL') ? $object_class : null; - } elseif ($type === 'studycourse') { + } elseif (in_array($type, + [ + 'studycourse', + 'stgteilabschnittmodul', + 'modulteilstgteilabschnitt', + ])) { $datafield->object_class = Request::option('object_class'); } else { $object_class = Request::getArray('object_class'); @@ -196,7 +206,6 @@ class Admin_DatafieldsController extends AuthenticatedController $this->render_action('type_select'); return; } - if (Request::isXhr() && $this->type_name) { PageLayout::setTitle(sprintf(_('Einen neuen Datentyp für die Kategorie "%s" erstellen'), $this->type_name)); } @@ -283,4 +292,58 @@ class Admin_DatafieldsController extends AuthenticatedController $filter->setOptions($this->allclasses, $this->class_filter); $sidebar->addWidget($filter); } + + /** + * Returns an array of replaceable fields, depending on object type. + * Array keys are the field names of the related table. + * Array values are a short name and description of the field. + * + * @param string $type The type of the object. + * @return array An array of replace + */ + public static function getReplaceFields(string $type): array + { + if ($type === 'stgteilabschnittmodul') { + return [ + 'dauer' => _('Dauer'), + 'kapazitaet' => _('Kapazität'), + 'kp' => _('Kreditpunkte'), + 'pruef_ebene' => _('Prüfungsebene'), + 'faktor_note' => _('Faktor Note'), + 'verantwortlich' => _('Verantwortlich (Freitext)'), + 'voraussetzung' => _('Teilnahmevoraussetzung'), + 'kompetenzziele' => _('Kompetenzziele'), + 'inhalte' => _('Inhalte'), + 'literatur' => _('Literatur'), + 'links' => _('Links'), + 'kommentar' => _('Kommentar'), + 'kommentar_kapazitaet' => _('Kommentar Kapazität'), + 'kommentar_sws' => _('Kommentar Semesterwochenstunden'), + 'kommentar_wl_selbst' => _('Kommentar Workload (selbstgestaltete Arbeitszeit)'), + 'kommentar_wl_pruef' => _('Kommentar Workload (Prüfung)'), + 'kommentar_note' => _('Kommentar Note'), + 'pruef_vorleistung' => _('Prüfungsvorleistung'), + 'pruef_leistung' => _('Leistung/Prüfungsform'), + 'pruef_wiederholung' => _('Wiederholungsprüfung'), + 'ersatztext' => _('Ersatztext'), + ]; + } elseif ($type === 'modulteilstgteilabschnitt') { + return [ + 'kp' => _('Kreditpunkte'), + 'bezeichnung' => _('Zusätliche Bezeichnung'), + 'voraussetzungen' => _('Teilnahmevoraussetzungen'), + 'kommentar' => _('Kommentar Modulteil'), + 'kommentar_kapazitaet' => _('Kommentar Kapazität'), + 'kommentar_wl_praesenz' => _('Kommentar Workload (Präsenzzeit)'), + 'kommentar_wl_bereitung' => _('Kommentar Workload (Vor-/Nachbereitung)'), + 'kommentar_wl_selbst' => _('Kommentar Workload (Modulteil selbstgestaltete Arbeitszeit)'), + 'kommentar_wl_pruef' => _('Kommentar Workload (Modulteil Prüfung)'), + 'pruef_vorleistung' => _('Prüfungsvorleistung'), + 'pruef_leistung' => _('Prüfungsleistung Modulteil'), + 'kommentar_pflicht' => _('Kommentar Anwesenheitspflicht'), + ]; + } else { + return []; + } + } } diff --git a/app/controllers/search/studiengaenge.php b/app/controllers/search/studiengaenge.php index 7035a63..210f243 100644 --- a/app/controllers/search/studiengaenge.php +++ b/app/controllers/search/studiengaenge.php @@ -335,8 +335,6 @@ class Search_StudiengaengeController extends MVVController ksort($fach_sem_data); $this->fach_sem_data = $fach_sem_data; - // Ausgabe des Namens ohne Fach (dieses ist im Zusatz bereits enthalten) - $this->studiengangTeilName = $this->stg_teil->getDisplayName(); // add option widget to show only modules with courses in the // selected semester diff --git a/app/controllers/shared/modul.php b/app/controllers/shared/modul.php index 2cb9a85..ffcfdb7 100644 --- a/app/controllers/shared/modul.php +++ b/app/controllers/shared/modul.php @@ -29,70 +29,40 @@ class Shared_ModulController extends AuthenticatedController ModuleManagementModel::setContentLanguage($display_language); $this->modul = Modul::find($modul_id); + if (!$this->modul) { + PageLayout::postError(_('Unbekanntes Modul')); + return; + } if (!$this->modul->hasPublicStatus()) { throw new AccessDeniedException(); } - if ($this->modul) { - $this->details_id = $this->modul->getId(); - - $type = 1; - if (count($this->modul->modulteile) == 1) { - $modulteil = $this->modul->modulteile->first(); - $type = 3; - if (count($modulteil->lvgruppen) > 0) { - $type = 2; - } - } else if (count($this->modul->modulteile) == 0) { - $type = 3; - } - - if (!$semester_id) { - $current_semester = Semester::findDefault(); - } else { - $current_semester = Semester::find($semester_id); + $this->type = 1; + if (count($this->modul->modulteile) < 2) { + $this->type = 3; + $modulteil = $this->modul->modulteile->first(); + if ($modulteil && count($modulteil->lvgruppen) > 0) { + $this->type = 2; } + } - $sws = 0; - $institut = new Institute($this->modul->responsible_institute->institut_id); - $modulteile_data = []; - foreach ($this->modul->modulteile as $modulteil) { - $modulteil_deskriptor = $modulteil->getDeskriptor(); - $sws += (int) $modulteil->sws; - $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name'] ?? ''; - $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulteil->nummer); - $modulteile_data[$modulteil->getId()] = [ - 'name' => $modulteil->getDisplayName(), - 'name_kurz' => $name_kurz, - 'voraussetzung' => $modulteil_deskriptor->voraussetzung, - 'pruef_leistung' => $modulteil_deskriptor->pruef_leistung, - 'pruef_vorleistung' => $modulteil_deskriptor->pruef_vorleistung, - 'kommentar' => $modulteil_deskriptor->kommentar, - 'kapazitaet' => $modulteil->kapazitaet, - 'lvGruppen' => [] - ]; - - $lvGruppen = Lvgruppe::findByModulteil($modulteil->getId()); - foreach ($lvGruppen as $lvGruppe) { - $ids = array_column($lvGruppe->getAssignedCoursesBySemester($current_semester['semester_id'], $GLOBALS['user']->id), 'seminar_id'); - $courses = Course::findMany($ids, 'order by Veranstaltungsnummer, Name'); - $modulteile_data[$modulteil->getId()]['lvGruppen'][$lvGruppe->getId()] = [ - 'courses' => $courses, - 'alt_texte' => $lvGruppe->alttext - ]; - } - } - $this->modulteile = $modulteile_data; - $this->deskriptor = $this->modul->getDeskriptor(); - $this->institut = $institut; - $this->semester = $current_semester; - $this->sws = $sws; + if (!$semester_id) { + $this->semester = Semester::findDefault(); + } else { + $this->semester = Semester::find($semester_id); + } - $this->pruef_ebene = $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$this->modul->pruef_ebene]['name'] ?? null; - $this->type = $type; - $this->self_url = $this->url_for('modul/show/' . $modul_id); - $this->detail_url = $this->url_for('modul/detail/' . $modul_id); - PageLayout::setTitle($this->modul->getDisplayName() . ' (' . _('Veranstaltungsübersicht') .')'); + $abschnitt_id = Request::option('abschnitt_id'); + $this->code = ''; + $this->title = ''; + $abschnitt_modul = $this->modul->abschnitte_modul->findOneBy('abschnitt_id', $abschnitt_id); + if ($abschnitt_modul) { + $this->modul->setReplaceDfAbschnitt($abschnitt_modul->abschnitt); + $this->code = trim($abschnitt_modul->modulcode); + $this->title = trim($abschnitt_modul->bezeichnung); } + + $this->pruef_ebene = $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$this->modul->pruef_ebene]['name'] ?? null; + PageLayout::setTitle($this->modul->getDisplayName() . ' (' . _('Veranstaltungsübersicht') .')'); } public function description_action($id) @@ -103,20 +73,12 @@ class Shared_ModulController extends AuthenticatedController throw new AccessDeniedException(); } $this->type = 1; - if (count($this->modul->modulteile) == 1) { - $modulteil = $this->modul->modulteile->first(); + if (count($this->modul->modulteile) < 2) { $this->type = 3; - if (count($modulteil->lvgruppen) > 0) { + $modulteil = $this->modul->modulteile->first(); + if ($modulteil && count($modulteil->lvgruppen) > 0) { $this->type = 2; } - } else if (count($this->modul->modulteile) == 0) { - $this->type = 3; - } - - if (!Request::get('sem_select')) { - $currentSemester = Semester::findCurrent(); - } else { - $currentSemester = Semester::find(Request::get('sem_select')); } $this->display_language = Request::get('display_language', $this->modul->original_language); @@ -124,21 +86,24 @@ class Shared_ModulController extends AuthenticatedController I18NString::setDefaultLanguage($this->modul->original_language); I18NString::setContentLanguage($this->display_language); - $this->semesterSelector = Semester::getSemesterSelector(null, $currentSemester['semester_id'], 'semester_id', false); - $this->pruefungsEbene = isset($GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$this->modul->pruef_ebene]) - ? $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$this->modul->pruef_ebene]['name'] - : null; - $this->modulDeskriptor = $this->modul->getDeskriptor(); - $this->startSemester = Semester::findByTimestamp($this->modul->start); + $this->start_semester = Semester::findByTimestamp($this->modul->start); if (!$this->modul->responsible_institute) { - $this->instituteName = null; + $this->institute_name = null; } elseif ($this->modul->responsible_institute->institute) { - $this->instituteName = $this->modul->responsible_institute->institute->name; + $this->institute_name = $this->modul->responsible_institute->institute->name; } else { - $this->instituteName = _('Unbekannte Einrichtung'); + $this->institute_name = _('Unbekannte Einrichtung'); + } + $abschnitt_id = Request::option('abschnitt_id'); + $this->code = ''; + $this->title = ''; + $this->abschnitt_modul = $this->modul->abschnitte_modul->findOneBy('abschnitt_id', $abschnitt_id); + if ($this->abschnitt_modul) { + $this->modul->setReplaceDfAbschnitt($this->abschnitt_modul->abschnitt); + $this->code = trim($this->abschnitt_modul->modulcode); + $this->title = trim($this->abschnitt_modul->bezeichnung); } - $this->semester = $currentSemester; PageLayout::setTitle($this->modul->getDisplayName() . ' (' . _('Vollständige Modulbeschreibung') .')'); } diff --git a/app/controllers/studiengaenge/shared_version.php b/app/controllers/studiengaenge/shared_version.php index 1607ce7..73715a7 100644 --- a/app/controllers/studiengaenge/shared_version.php +++ b/app/controllers/studiengaenge/shared_version.php @@ -449,43 +449,70 @@ abstract class SharedVersionController extends MVVController public function modul_zuordnung_action($abschnitt_modul_id) { $this->zuordnung = StgteilabschnittModul::find($abschnitt_modul_id); - if ($this->zuordnung->isNew()) { + if (!$this->zuordnung) { PageLayout::postError(_('Unbekannte Zuordnung')); $this->redirect($this->action_url('index')); return; } else { PageLayout::setTitle(_('Modulzuordnung bearbeiten')); - $success_message = _('Die Modulzuordnung "%s" wurde geändert.'); } - $success = false; + $this->render_template('studiengaenge/versionen/modul_zuordnung', $this->layout); + } + + public function modul_zuordnung_store_action($abschnitt_modul_id) + { + $this->zuordnung = StgteilabschnittModul::find($abschnitt_modul_id); + if (!$this->zuordnung) { + PageLayout::postError(_('Unbekannte Zuordnung')); + $this->redirect($this->action_url('index')); + return; + } if (Request::submitted('store')) { CSRFProtection::verifyUnsafeRequest(); $this->zuordnung->bezeichnung = Request::i18n('bezeichnung')->trim(); $this->zuordnung->flexnow_modul = trim(Request::get('flexnow_modul')); $this->zuordnung->modulcode = trim(Request::get('modulcode')); + // update data fields + $data_field_values = Request::getArray('datafields'); + $invalid_data_fields = []; + $data_fields_updated = false; + foreach ($this->zuordnung->datafields as $data_field) { + $tdf = $data_field->getTypedDatafield(); + $tdf->setValueFromSubmit($data_field_values[$data_field->datafield_id]); + if ($tdf->isValid() && $tdf->store()) { + $data_fields_updated = true; + } else { + $invalid_data_fields[] = $tdf->getName(); + } + } $stored = $this->zuordnung->store(); if ($stored !== false) { - $success = true; - if (!Request::isXhr()) { - if ($stored) { - PageLayout::postSuccess(sprintf( - $success_message, - htmlReady($this->zuordnung->getDisplayName()) - )); - } else { - PageLayout::postInfo(_('Es wurden keine Änderungen vorgenommen.')); - } - $this->redirect($this->action_url('details_abschnitt/' . $this->zuordnung->abschnitt_id)); + if ($stored || $data_fields_updated) { + PageLayout::postSuccess(sprintf( + _('Die Modulzuordnung "%s" wurde geändert.'), + htmlReady($this->zuordnung->getDisplayName()) + )); + } else { + PageLayout::postInfo(_('Es wurden keine Änderungen vorgenommen.')); } - } - } - if (Request::isXhr()) { - if ($success) { - $this->details_abschnitt_action($this->zuordnung->abschnitt_id); + $this->relocate($this->action_url('details_abschnitt/' . $this->zuordnung->abschnitt_id)); + return; } else { - $this->render_template('studiengaenge/versionen/modul_zuordnung'); + PageLayout::postError(_('Die Änderungen an der Modulzuordnung konnten nicht gespeichert werden.')); + } + if (count($invalid_data_fields)) { + $message = ngettext( + 'Das folgende Datenfeld wurde falsch angegeben:', + 'Die folgenden Datenfelder wurden falsch angegeben:', + count($invalid_data_fields) + ); + PageLayout::postError( + $message, + array_map('htmlReady', $invalid_data_fields) + ); } } + $this->redirect($this->action_url('modul_zuordnung/' . $this->zuordnung->id)); } public function delete_modul_action($abschnitt_id, $modul_id) @@ -548,11 +575,34 @@ abstract class SharedVersionController extends MVVController if ($this->modulteil) { $this->abschnitt_modul = StgteilabschnittModul::find($abschnitt_modul_id); if ($this->abschnitt_modul) { + // Store an additional ModulteilStgteilAbschnitt-Object for the relations to the data fields. + // Use 0 as value for the field fachsemester. + $this->assignment = new ModulteilStgteilabschnitt( + [ + $this->modulteil->id, + $this->abschnitt_modul->abschnitt_id, + 0 + ] + ); if (Request::submitted('store')) { CSRFProtection::verifyUnsafeRequest(); $fachsem = $this->abschnitt_modul->getAllFachsemester($this->modulteil->id); $status = Request::optionArray('status'); $is_modified = false; + $this->assignment->store(); + // update datafields + $data_field_values = Request::getArray('datafields'); + $invalid_data_fields = []; + $data_fields_updated = false; + foreach ($this->assignment->datafields as $data_field) { + $tdf = $data_field->getTypedDatafield(); + $tdf->setValueFromSubmit($data_field_values[$data_field->datafield_id]); + if ($tdf->isValid() && $tdf->store()) { + $data_fields_updated = true; + } else { + $invalid_data_fields[] = $tdf->getName(); + } + } foreach (array_keys(Request::intArray('fachsemester')) as $i) { if (isset($fachsem[$i])) { $fachsem[$i]->differenzierung = $status[$i]; @@ -574,7 +624,7 @@ abstract class SharedVersionController extends MVVController $is_modified = true; } } - if ($is_modified) { + if ($is_modified || $data_fields_updated) { PageLayout::postSuccess(sprintf( _('Die Zuordnung der Fachsemester zum Modulteil "%s" des Moduls "%s" im Abschnitt "%s" wurde geändert.'), htmlReady($this->modulteil->getDisplayName()), @@ -586,9 +636,21 @@ abstract class SharedVersionController extends MVVController _('Es wurden keine Änderungen an der Zuordnung der Fachsemester vorgenommen.') ); } + if (count($invalid_data_fields)) { + $message = ngettext( + 'Das folgende Datenfeld wurde falsch angegeben:', + 'Die folgenden Datenfelder wurden falsch angegeben:', + count($invalid_data_fields) + ); + PageLayout::postError( + $message, + array_map('htmlReady', $invalid_data_fields) + ); + } $this->relocate($this->action_url('details_abschnitt/' . $this->abschnitt_modul->abschnitt_id . '/' . $this->abschnitt_modul->modul_id)); return; } + PageLayout::setTitle(_('Angaben zum verknüpften Modulteil')); $this->render_template('studiengaenge/versionen/modulteil_semester', $this->layout); } else { $this->render_nothing(); diff --git a/app/views/admin/datafields/edit.php b/app/views/admin/datafields/edit.php index c3f67b4..7958620 100644 --- a/app/views/admin/datafields/edit.php +++ b/app/views/admin/datafields/edit.php @@ -6,6 +6,7 @@ * @var string $datafield_id * @var DataFieldEntry $datafield_entry * @var array $institutes + * @var array $replace_fields */ use Studip\Button, Studip\LinkButton; @@ -99,6 +100,15 @@ use Studip\Button, Studip\LinkButton; <option value="mehrfach_settings"<?= mb_strpos($item->object_class, 'mehrfach_settings') !== false ? ' selected' : '' ?>><?= _('Mehrfach-Studiengänge (Abschnitt "Einstellungen")') ?></option> <option value="mehrfach_info"<?= mb_strpos($item->object_class, 'mehrfach_info') !== false ? ' selected' : '' ?>><?= _('Mehrfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ?></option> </select> + <? elseif ($item->object_type === 'stgteilabschnittmodul' || $item->object_type === 'modulteilstgteilabschnitt'): ?> + <?= _('Überschreibt') ?> + + <select name="object_class"> + <option value=""><?= _('Zusätzliches Datenfeld (keine Ersetzung)') ?></option> + <? foreach (Admin_DatafieldsController::getReplaceFields($item->object_type) as $key => $name): ?> + <option value="<?= $key ?>"<?= $key === $item->object_class ? ' selected' : '' ?>><? printf('%s (%s)', $key, htmlReady($name)) ?></option> + <? endforeach; ?> + </select> <? else : ?> <?= _('Nutzerstatus') ?>: diff --git a/app/views/admin/datafields/index.php b/app/views/admin/datafields/index.php index 64d6d6f..5d959d7 100644 --- a/app/views/admin/datafields/index.php +++ b/app/views/admin/datafields/index.php @@ -31,7 +31,7 @@ <th><?= _('Feldtyp') ?></th> <th style="white-space: nowrap"> <?= _('Typ') ?> - <?= tooltipIcon(_('Veranstaltungskategorie, Einrichtungstyp, Sprache bzw. Nutzerstatus')) ?> + <?= tooltipIcon(_('Veranstaltungskategorie, Einrichtungstyp, Sprache, ersetztes Feld bzw. Nutzerstatus')) ?> </th> <th> <?= _('Institution') ?> @@ -58,7 +58,7 @@ <? else: ?> <th class="toggle-indicator" colspan="11"> <? endif; ?> - <? if (empty($datafields_list[$key])): ?> + <? if (empty($data)): ?> <?= sprintf(_('Datenfelder für %s'), $allclasses[$key]) ?> <? else: ?> <a name="<?= $key ?>" class="toggler" href="<?= $controller->url_for('admin/datafields/index/' . $key) ?>"> @@ -114,6 +114,9 @@ 'mehrfach_info' => _('Mehrfach-Studiengänge (Abschnitt "Inhalte und Informationen")') ];?> <?= $object_classes[$val->object_class] ?> + <? elseif ($key === 'stgteilabschnittmodul' || $key === 'modulteilstgteilabschnitt'): ?> + <? $replace_fields = Admin_DatafieldsController::getReplaceFields($key); ?> + <? printf('%s (%s)', $val->object_class, $replace_fields[$val->object_class]) ?> <? else: ?> <?= $val->object_class !== null ? DataField::getReadableUserClass($val->object_class) : _('alle')?> <? endif; ?> diff --git a/app/views/admin/datafields/new.php b/app/views/admin/datafields/new.php index c749ff9..2826589 100644 --- a/app/views/admin/datafields/new.php +++ b/app/views/admin/datafields/new.php @@ -7,6 +7,7 @@ * @var array $institutes * @var Institute $item * @var DataField $datafield + * @var array $replace_fields */ use Studip\Button, Studip\LinkButton; @@ -45,8 +46,22 @@ use Studip\Button, Studip\LinkButton; <?= _('Veranstaltungskategorie') ?> <? elseif ($object_typ === 'inst'): ?> <?= _('Einrichtungstyp') ?> - <? elseif ($object_typ === 'moduldeskriptor' || $object_typ === 'modulteildeskriptor') : ?> + <? elseif (in_array( + $object_typ, + [ + 'moduldeskriptor', + 'modulteildeskriptor', + ] + )) : ?> <?= _('Sprache') ?> + <? elseif (in_array( + $object_typ, + [ + 'stgteilabschnittmodul', + 'modulteilstgteilabschnitt', + ] + )): ?> + <?= _('Ersetzt Feld') ?> <? elseif ($object_typ === 'studycourse'): ?> <?= _('Typ/Abschnitt') ?> <? else: ?> @@ -69,17 +84,29 @@ use Studip\Button, Studip\LinkButton; <?= htmlReady($val['name']) ?> </option> <? endforeach; ?> - <? elseif ($object_typ === 'moduldeskriptor') : ?> + <? elseif (in_array( + $object_typ, + [ + 'moduldeskriptor', + 'modulteildeskriptor', + ]) + ): ?> <select multiple name="object_class[]" required> <option value="NULL" selected><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option> <? foreach ($GLOBALS['CONTENT_LANGUAGES'] as $key => $value) : ?> <option value="<?= htmlReady($key) ?>"><?= htmlReady($value['name']) ?></option> <? endforeach; ?> - <? elseif ($object_typ === 'modulteildeskriptor') : ?> - <select multiple name="object_class[]" required> - <option value="NULL" selected><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option> - <? foreach ($GLOBALS['CONTENT_LANGUAGES'] as $key => $value) : ?> - <option value="<?= htmlReady($key) ?>"><?= htmlReady($value['name']) ?></option> + <? elseif (in_array( + $object_typ, + [ + 'stgteilabschnittmodul', + 'modulteilstgteilabschnitt', + ]) + ): ?> + <select name="object_class" required> + <option value="NULL" selected><?= _('Zusätzliches Datenfeld (keine Ersetzung)') ?></option> + <? foreach (Admin_DatafieldsController::getReplaceFields($object_typ) as $key => $value) : ?> + <option value="<?= htmlReady($key) ?>"><? printf('%s (%s)', $key, htmlReady($value)) ?></option> <? endforeach; ?> <? elseif ($object_typ === 'studycourse') : ?> <select name="object_class" required> @@ -119,6 +146,13 @@ use Studip\Button, Studip\LinkButton; </select> </label> + <? if (!in_array( + $object_typ, + [ + 'stgteilabschnittmodul', + 'modulteilstgteilabschnitt', + ]) + ): ?> <label> <?= _('Einrichtung') ?> <select name="institut_id" class="nested-select"> @@ -132,6 +166,7 @@ use Studip\Button, Studip\LinkButton; <? endforeach; ?> </select> </label> + <? endif; ?> <? if ($object_typ === 'user') :?> <label> @@ -164,8 +199,20 @@ use Studip\Button, Studip\LinkButton; <textarea name="description"></textarea> </label> + <? endif; ?> + <? if ($object_typ === 'stgteilabschnittmodul' || $object_typ === 'modulteilstgteilabschnitt'): ?> + <label> + <?= _('Überschreibt') ?> + <select name="replace_field"> + <option value=""><?= _('Zusätzliches Datenfeld (keine Ersetzung)') ?></option> + <? foreach ($replace_fields as $key => $name): ?> + <option value="<?= $key ?>"><?= htmlReady($name) ?></option> + <? endforeach; ?> + </select> + </label> <? endif; ?> + <? if ($object_typ === 'user'): ?> <label> <input type="checkbox" name="is_userfilter" value="1"> diff --git a/app/views/search/module/_modul.php b/app/views/search/module/_modul.php index 2fdd755..1ac6280 100644 --- a/app/views/search/module/_modul.php +++ b/app/views/search/module/_modul.php @@ -8,7 +8,7 @@ ?> <tbody class="<?= (isset($modul_id) && $modul_id == $modul->id) ? 'not-collapsed' : 'collapsed' ?>"> <tr class="table-header header-row" id="modul_<?= htmlReady($modul->id) ?>"> - <td style="vertical-align: middle; text-align: center;"> + <td> <a data-dialog="size=auto" title="<?= htmlReady($modul->getDisplayName()) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= $controller->link_for('shared/modul/description/' . $modul->id) ?>"> <?= Icon::create('log')->asImg(['title' => _('Vollständige Modulbeschreibung')]) ?> </a> diff --git a/app/views/search/module/index.php b/app/views/search/module/index.php index a2d5c19..724ff27 100644 --- a/app/views/search/module/index.php +++ b/app/views/search/module/index.php @@ -25,13 +25,12 @@ <col> <col> <col> + <col> </colgroup> <thead> <tr> <th> - <abbr title="<?= _('Moduldeskriptor') ?>"> - <?= Icon::create('log', Icon::ROLE_INFO) ?> - </abbr> + <?= Icon::create('log', Icon::ROLE_INFO, ['title' => _('Modulbeschreibung')]) ?> </th> <th class="mvv-search-modules-row"><?= _('Modultitel') ?></th> <th><?= _('Gültigkeit') ?></th> diff --git a/app/views/search/studiengaenge/verlauf.php b/app/views/search/studiengaenge/verlauf.php index d5357bc..3046673 100644 --- a/app/views/search/studiengaenge/verlauf.php +++ b/app/views/search/studiengaenge/verlauf.php @@ -85,11 +85,25 @@ <tr> <td<?= count($modul['modulTeile']) > 1 ? ' style="border: none;"' : '' ?>> <? $abschnitt_modul = StgteilabschnittModul::findOneBySQL('`abschnitt_id` = ? AND `modul_id` = ?', [$abschnitt_id, $modul_id]) ?> - <a data-dialog="size=auto" title="<?= htmlReady($modul['name']) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" href="<?= $controller->link_for('shared/modul/description/' . $modul_id, ['display_language' => ModuleManagementModel::getLanguage()]) ?>"> + <a data-dialog="size=auto" + title="<?= htmlReady($modul['name']) . ' (' . _('Vollständige Modulbeschreibung') . ')' ?>" + href="<?= $controller->link_for('shared/modul/description/' . $modul_id, + [ + 'display_language' => ModuleManagementModel::getLanguage(), + 'abschnitt_id' => $abschnitt_id, + ]) ?>"> <?= Icon::create('log', Icon::ROLE_CLICKABLE, ['title' => _('Vollständige Modulbeschreibung')]) ?> </a> <? if ($modul['courses']) : ?> - <a data-dialog href="<?= $controller->link_for('shared/modul/overview', $modul_id, $active_sem->getId(), ['display_language' => ModuleManagementModel::getLanguage()]) ?>"> + <a data-dialog + href="<?= $controller->link_for( + 'shared/modul/overview', + $modul_id, + $active_sem->id, + [ + 'display_language' => ModuleManagementModel::getLanguage(), + 'abschnitt_id' => $abschnitt_id, + ]); ?>"> <?= htmlReady($abschnitt_modul->getDisplayName()) ?> </a> <? else: ?> diff --git a/app/views/shared/modul/_modul.php b/app/views/shared/modul/_modul.php index f3ebfd7..afff494 100644 --- a/app/views/shared/modul/_modul.php +++ b/app/views/shared/modul/_modul.php @@ -1,25 +1,23 @@ <?php /** * @var Modul $modul - * @var ModulDeskriptor $modulDeskriptor * @var string $affect_id - * @var array $modulVerantwortung * @var int $type - * @var int $nummer_modulteil - * @var array $note - * @var string $num_bezeichnung + * @var StgteilabschnittModul|null $abschnitt_modul + * @var string $code + * @var string $title */ -$modulDeskriptor = $modul->getDeskriptor($display_language ?? null); +$deskriptor = $modul->getDeskriptor($display_language ?? null); ?> -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul"> +<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->id ?>" data-mvv-type="modul"> <colgroup> <col width="30%"> <col width="70%"> </colgroup> <thead> <tr> - <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.code"><?= htmlReady($modul->code) ?></th> - <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.kp" style="text-align: right;"><?= sprintf("%d CP", $modul->kp) ?></th> + <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.code"><?= htmlReady($code ?: $modul->code) ?></th> + <th class="mvv-modul-details-head" data-mvv-field="mvv_modul.kp" style="text-align: right;"><?= sprintf("%d CP", $modul->getReplacedValue('kp')) ?></th> </tr> <? if ($modul->fassung_nr): ?> <tr> @@ -37,20 +35,20 @@ $modulDeskriptor = $modul->getDeskriptor($display_language ?? null); <tbody> <tr> <td><strong><?= _('Modulbezeichnung') ?></strong></td> - <td data-mvv-field="mvv_modul.bezeichnung"><?= htmlReady($modulDeskriptor->bezeichnung) ?></td> + <td data-mvv-field="mvv_modul.bezeichnung"><?= htmlReady($title ?: $deskriptor->bezeichnung) ?></td> </tr> <tr> <td><strong><?= _('Modulcode') ?></strong></td> - <td data-mvv-field="mvv_modul.code"><?= htmlReady($modul->code) ?></td> + <td data-mvv-field="mvv_modul.code"><?= htmlReady($code ?: $modul->code) ?></td> </tr> <tr> <td><strong><?= _('Semester der erstmaligen Durchführung') ?></strong></td> - <td data-mvv-field="mvv_modul.start"><?= htmlReady($startSemester['name'] ?? '') ?></td> + <td data-mvv-field="mvv_modul.start"><?= htmlReady($start_semester['name'] ?? '') ?></td> </tr> - <? if (!empty($instituteName)) : ?> + <? if (!empty($institute_name)) : ?> <tr> <td><strong><?= _('Fachbereich/Institut') ?></strong></td> - <td data-mvv-field="mvv_modul_inst"><?= htmlReady($instituteName) ?></td> + <td data-mvv-field="mvv_modul_inst"><?= htmlReady($institute_name) ?></td> </tr> <? endif; ?> <tr> @@ -116,25 +114,25 @@ $modulDeskriptor = $modul->getDeskriptor($display_language ?? null); <? endforeach; ?> </td> </tr> - <? if (trim($modulDeskriptor->verantwortlich)): ?> + <? if (trim($deskriptor->getReplacedValue('verantwortlich'))): ?> <tr> <td><strong><?= _('Weitere verantwortliche Personen') ?></strong></td> <td> - <?= formatReady($modulDeskriptor->verantwortlich) ?> + <?= formatReady($deskriptor->getReplacedValue('verantwortlich')) ?> </td> </tr> <? endif; ?> <tr> <td><strong><?= _('Teilnahmevoraussetzungen') ?></strong></td> - <td data-mvv-field="mvv_modul_deskriptor.voraussetzung"><?= formatReady($modulDeskriptor->voraussetzung) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.voraussetzung"><?= formatReady($deskriptor->getReplacedValue('voraussetzung')) ?></td> </tr> <tr> <td><strong><?= _('Kompetenzziele') ?></strong></td> - <td data-mvv-field="mvv_modul_deskriptor.kompetenzziele"><?= formatReady($modulDeskriptor->kompetenzziele) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.kompetenzziele"><?= formatReady($deskriptor->getReplacedValue('kompetenzziele')) ?></td> </tr> <tr> <td><strong><?= _('Modulinhalte') ?></strong></td> - <td data-mvv-field="mvv_modul_deskriptor.inhalte"><?= formatReady($modulDeskriptor->inhalte) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.inhalte"><?= formatReady($deskriptor->getReplacedValue('inhalte')) ?></td> </tr> <? if (!isset($type) || $type !== 3) : ?> <tr> @@ -164,19 +162,26 @@ $modulDeskriptor = $modul->getDeskriptor($display_language ?? null); </tr> <tr> <td><strong><?= _('Angebotsrhythmus Modul') ?></strong></td> - <td data-mvv-field="mvv_modul_deskriptor.turnus"><?= htmlReady($modulDeskriptor->turnus) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.turnus"><?= htmlReady($deskriptor->turnus) ?></td> </tr> <tr> <td><strong><?= _('Aufnahmekapazität Modul') ?></strong></td> - <td data-mvv-field="mvv_modul.kapazitaet"><?= htmlReady(trim($modul->kapazitaet)) ?: _('unbegrenzt') ?> <?= MVVController::trim($modulDeskriptor->kommentar_kapazitaet) ? sprintf("(%s)", formatReady($modulDeskriptor->kommentar_kapazitaet)) : '' ?></td> + <td data-mvv-field="mvv_modul.kapazitaet"> + <?= htmlReady(trim($modul->getReplacedValue('kapazitaet')) ?: _('unbegrenzt')) ?> + <?= MVVController::trim($deskriptor->getReplacedValue('kommentar_kapazitaet')) + ? sprintf("(%s)", formatReady($deskriptor->getReplacedValue('kommentar_kapazitaet'))) + : '' ?> + </td> </tr> <tr> <td><strong><?= _('Prüfungsebene') ?></strong></td> - <td data-mvv-field="mvv_modul.pruef_ebene"><?= htmlReady($pruefungsEbene ?? '') ?></td> + <td data-mvv-field="mvv_modul.pruef_ebene"> + <?= htmlReady($GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->getReplacedValue('pruef_ebene')] ?? '') ?> + </td> </tr> <tr> <td><strong><?= _('Credit-Points') ?></strong></td> - <td data-mvv-field="mvv_modul.kp"><?= sprintf("%d CP", htmlReady($modul->kp)) ?></td> + <td data-mvv-field="mvv_modul.kp"><?= sprintf("%d CP", htmlReady($modul->getReplacedValue('kp'))) ?></td> </tr> <tr> <td><strong><?= _('Modulabschlussnote') ?></strong></td> @@ -212,25 +217,38 @@ $modulDeskriptor = $modul->getDeskriptor($display_language ?? null); <?= implode('; ', $note) . '. ' ?> <? endif; ?> <? endif; ?> - <?= formatReady(trim($modulDeskriptor->kommentar_note)) ?> + <?= formatReady(trim($deskriptor->getReplacedValue('kommentar_note'))) ?> </td> </tr> <tr> <td><strong><?= _('Faktor der Modulnote für die Endnote des Studiengangs') ?></strong></td> - <td data-mvv-field="mvv_modul.faktor_note"><?= htmlReady($modul->faktor_note) ?></td> + <td data-mvv-field="mvv_modul.faktor_note"><?= htmlReady($modul->getReplacedValue('faktor_note')) ?></td> </tr> - <? if (trim($modulDeskriptor->kommentar)) : ?> + <? if (trim($deskriptor->getReplacedValue('kommentar'))) : ?> <tr> <td><strong><?= _('Hinweise') ?></strong></td> - <td data-mvv-field="mvv_modul_deskriptor.kommentar"><?= formatReady($modulDeskriptor->kommentar) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.kommentar"><?= formatReady($deskriptor->getReplacedValue('kommentar')) ?></td> </tr> <? endif; ?> - <? foreach ($modulDeskriptor->datafields as $entry) : ?> - <? $df = $entry->getTypedDatafield(); ?> - <tr> - <td><strong><?= htmlReady($df->getName()) ?></strong></td> - <td><?= $df->getDisplayValue(); ?></td> - </tr> + <? foreach ($deskriptor->datafields as $entry) : ?> + <? $df = $entry->getTypedDatafield(); ?> + <tr> + <td><strong><?= htmlReady($df->getName()) ?></strong></td> + <td><?= $df->getDisplayValue(); ?></td> + </tr> <? endforeach; ?> + <? if ($abschnitt_modul) : ?> + <? $data_fields = $abschnitt_modul->datafields->filter( + fn(DatafieldEntryModel $d): bool => ($d->datafield->object_class ?? '') === '') ?> + <? foreach ($data_fields as $entry) : ?> + <? if (trim($entry->content)) : ?> + <? $df = $entry->getTypedDatafield(); ?> + <tr> + <td><strong><?= htmlReady($df->getName()) ?></strong></td> + <td><?= $df->getDisplayValue(); ?></td> + </tr> + <? endif; ?> + <? endforeach; ?> + <? endif; ?> </tbody> </table> diff --git a/app/views/shared/modul/_modul_ohne_lv.php b/app/views/shared/modul/_modul_ohne_lv.php index f3c74ec..013f4cb 100644 --- a/app/views/shared/modul/_modul_ohne_lv.php +++ b/app/views/shared/modul/_modul_ohne_lv.php @@ -1,14 +1,33 @@ -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul"> +<?php +/** + * @var Modul $modul + * @var StgteilabschnittModul|null $abschnitt_modul + * @var string $code + * @var string $title + */ +?> +<? $deskriptor = $modul->getDeskriptor(); ?> +<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modul->id; ?>" data-mvv-type="modul"> <tbody> <? $modulSumme = $modul->wl_selbst + $modul->wl_pruef ?> <tr> <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"><?= htmlReady($modul->wl_selbst) ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_selbst ?? '') ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_selbst)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"> + <?= htmlReady($modul->getReplacedValue('wl_selbst')) ?> + <?= MVVController::trim($deskriptor->getReplacedValue('kommentar_wl_selbst')) + ? sprintf(" (%s)", formatReady($deskriptor->getReplacedValue('kommentar_wl_selbst'))) + : '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"><?= htmlReady($modul->wl_pruef) ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_pruef ?? '') ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_pruef)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"> + <?= htmlReady($modul->getReplacedValue('wl_pruef')) ?> + <?= MVVController::trim($deskriptor->getReplacedValue('kommentar_wl_pruef')) + ? sprintf(" (%s)", formatReady($deskriptor->getReplacedValue('kommentar_wl_pruef'))) + : '' ?> + </td> </tr> <tr> @@ -17,21 +36,27 @@ </tr> </tbody> </table> -<table class="mvv-modul-details" data-mvv-id="<?= isset($modulDeskriptor) ? $modulDeskriptor->getId() : ''; ?>" data-mvv-type="moduldeskriptor"> +<table class="mvv-modul-details" data-mvv-id="<?= $deskriptor->id ?>" data-mvv-type="moduldeskriptor"> <tbody> - <? if (trim($modulDeskriptor->pruef_vorleistung ?? '')) : ?> + <? if (trim($deskriptor->getReplacedValue('pruef_vorleistung'))) : ?> <tr> <td style="width: 30%;"><strong><?= _('Prüfungsvorleistung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung" ><?= formatReady($modulDeskriptor->pruef_vorleistung ?? '') ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung" > + <?= formatReady($deskriptor->getReplacedValue('pruef_vorleistung')) ?> + </td> </tr> <? endif; ?> <tr> <td style="width: 30%;"><strong><?= _('Prüfungsform') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_leistung"><?= formatReady($modulDeskriptor->pruef_leistung ?? '') ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_leistung"> + <?= formatReady($deskriptor->getReplacedValue('pruef_leistung')) ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Wiederholungsprüfung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_wiederholung"><?= formatReady($modulDeskriptor->pruef_wiederholung ?? '') ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul_deskriptor.pruef_wiederholung"> + <?= formatReady($deskriptor->getReplacedValue('pruef_wiederholung')) ?> + </td> </tr> </tbody> </table> diff --git a/app/views/shared/modul/_modullv.php b/app/views/shared/modul/_modullv.php index 70ffd64..2675f31 100644 --- a/app/views/shared/modul/_modullv.php +++ b/app/views/shared/modul/_modullv.php @@ -1,102 +1,175 @@ -<? $modulTeil = $modul->modulteile->first(); ?> -<? $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language ?? null); ?> -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeil->id; ?>" data-mvv-type="modulteil"> +<?php +/** + * @var Modul $modul + * @var StgteilabschnittModul|null $abschnitt_modul + */ +?> +<? $modulteil = $modul->modulteile->first(); ?> +<? $modulteil_deskriptor = $modulteil->getDeskriptor(); ?> +<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <tbody> - <? $modulTeilSumme = $modulTeil->wl_praesenz + $modulTeil->wl_bereitung + $modulTeil->wl_selbst + $modulTeil->wl_pruef ?> + <? $modulteil_summe = $modulteil->wl_praesenz + $modulteil->wl_bereitung + $modulteil->wl_selbst + $modulteil->wl_pruef ?> <tr> <td style="width: 30%;"><strong><?= _('Lehrveranstaltungsform') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?? '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?? '' ?></td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Veranstaltungstitel') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"> + <?= htmlReady($modulteil_deskriptor->getReplacedValue('bezeichnung')) ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('SWS') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.sws mvv_modulteil_deskriptor.sws_alternative"><?= $modulTeil->sws ?: '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.sws mvv_modulteil_deskriptor.sws_alternative"> + <?= $modulteil->sws ?: '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload Präsenz') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"> + <?= $modulteil->getReplacedValue('wl_praesenz') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_praesenz')) + ? sprintf(" (%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_praesenz'))) + : '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload Vor- / Nachbereitung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"> + <?= $modulteil->getReplacedValue('wl_bereitung') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_bereitung')) + ? sprintf(" (%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_bereitung'))) + : '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"> + <?= $modulteil->getReplacedValue('wl_selbst') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_selbst')) + ? sprintf(" (%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_selbst'))) + : '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= $modulTeil->wl_pruef ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? sprintf(" (%s)", formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"> + <?= $modulteil->getReplacedValue('wl_pruef') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_pruef')) + ? sprintf(" (%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_pruef'))) + : '' ?> + </td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload insgesamt') ?></strong></td> - <td style="width: 70%;"><?= $modulTeilSumme ?></td> + <td style="width: 70%;"><?= $modulteil_summe ?></td> </tr> - <? if ((int) $modul->wl_selbst) : ?> + <? if ((int) $modul->getReplacedValue('wl_selbst')) : ?> <tr> <td style="width: 30%;"><strong><?= _('Workload selbstgestaltete Arbeit (modulbezogen') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"><?= $modul->wl_selbst ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_selbst) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_selbst)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul.wl_selbst mvv_modul_deskriptor.kommentar_wl_selbst"> + <?= $modul->getReplacedValue('wl_selbst') ?> + <?= MVVController::trim($modul->deskriptoren->getReplacedValue('kommentar_wl_selbst')) + ? sprintf(" (%s)", formatReady($modul->deskriptoren->getReplacedValue('kommentar_wl_selbst'))) + : '' ?> + </td> </tr> <? endif; ?> - <? if ((int) $modul->wl_pruef) : ?> + <? if ((int) $modul->getReplacedValue('wl_pruef')) : ?> <tr> <td style="width: 30%;"><strong><?= _('Workload Prüfung incl. Vorbereitung (modulbezogen)') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"><?= $modul->wl_pruef ?> <?= MVVController::trim($modulDeskriptor->kommentar_wl_pruef) ? sprintf(" (%s)", formatReady($modulDeskriptor->kommentar_wl_pruef)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modul.wl_pruef mvv_modul_deskriptor.kommentar_wl_pruef"> + <?= $modul->getReplacedValue('wl_pruef') ?> + <?= MVVController::trim($modul->deskriptoren->getReplacedValue('kommentar_wl_pruef')) + ? sprintf(" (%s)", formatReady($modul->deskriptoren->getReplacedValue('kommentar_wl_pruef'))) + : '' ?> + </td> </tr> <? endif; ?> - <? if ($modul->wl_selbst + $modul->wl_pruef) : ?> + <? if (intval($modul->getReplacedValue('wl_selbst')) + intval($modul->getReplacedValue('wl_pruef'))) : ?> <tr> <td style="width: 30%;"><strong><?= _('Workload Modul insgesamt') ?></strong></td> - <td style="width: 70%;"><?= $modulTeilSumme + $modul->wl_selbst + $modul->wl_pruef ?></td> + <td style="width: 70%;"><?= + $modulteil_summe + + intval($modul->getReplacedValue('wl_selbst')) + + intval($modul->getReplacedValue('wl_pruef')) ?></td> </tr> <? endif; ?> </tbody> </table> -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeilDeskriptor->id; ?>" data-mvv-type="modulteil_deskriptor"> +<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulteil_deskriptor->id; ?>" data-mvv-type="modulteil_deskriptor"> <tbody> - <? if (trim($modulTeilDeskriptor->pruef_vorleistung)) : ?> + <? if (trim($modulteil_deskriptor->pruef_vorleistung)) : ?> <tr> <td style="width: 30%;"><strong><?= _('Prüfungsvorleistung') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"><?= formatReady($modulTeilDeskriptor->pruef_vorleistung) ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"> + <?= formatReady($modulteil_deskriptor->getReplacedValue('pruef_vorleistung')) ?> + </td> </tr> <? endif; ?> <tr> <td style="width: 30%;"><strong><?= _('Prüfungsform') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"><?= formatReady($modulTeilDeskriptor->pruef_leistung) ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"> + <?= formatReady($modulteil_deskriptor->getReplacedValue('pruef_leistung')) ?> + </td> </tr> </tbody> </table> -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeil->id; ?>" data-mvv-type="modulteil"> +<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <tbody> <tr> <td style="width: 30%;"><strong><?= _('Angebotsrhythmus') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.semester"><?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulTeil->semester]['name'] ?? '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.semester"><?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulteil->semester]['name'] ?? '' ?></td> </tr> <tr> <td style="width: 30%;"><strong><?= _('Aufnahmekapazität') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.kapazitaet mvv_modulteil_deskriptor.kommentar_kapazitaet"><?= trim($modulTeil->kapazitaet) ?: _('unbegrenzt') ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_kapazitaet) ? sprintf("(%s)", formatReady($modulTeilDeskriptor->kommentar_kapazitaet)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.kapazitaet mvv_modulteil_deskriptor.kommentar_kapazitaet"> + <?= trim($modulteil->kapazitaet) ?: _('unbegrenzt') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_kapazitaet')) + ? sprintf("(%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_kapazitaet'))) + : '' ?> + </td> </tr> - <? if ($modulTeil->pflicht) : ?> + <? if ($modulteil->pflicht) : ?> <tr> <td style="width: 30%;"><strong><?= _('Anwesenheitspflicht') ?></strong></td> - <td style="width: 70%;" data-mvv-field="mvv_modulteil.pflicht mvv_modulteil_deskriptor.kommentar_pflicht"><?= $modulTeil->pflicht ? _('Ja') : _('Nein') ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_pflicht) ? sprintf("(%s)", formatReady($modulTeilDeskriptor->kommentar_pflicht)) : '' ?></td> + <td style="width: 70%;" data-mvv-field="mvv_modulteil.pflicht mvv_modulteil_deskriptor.kommentar_pflicht"> + <?= $modulteil->pflicht ? _('Ja') : _('Nein') ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_pflicht')) + ? sprintf("(%s)", formatReady($modulteil_deskriptor->getReplacedValue('kommentar_pflicht'))) + : '' ?> + </td> </tr> <? endif; ?> </tbody> </table> -<? if (count($modulTeilDeskriptor->datafields)) : ?> -<table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulTeilDeskriptor->id; ?>" data-mvv-type="modulteil_deskriptor"> - <tbody> - <? foreach ($modulTeilDeskriptor->datafields as $entry) : ?> - <? $df = $entry->getTypedDatafield(); ?> - <tr> - <td style="width: 30%;"><strong><?= htmlReady($df->getName()) ?></strong></td> - <td style="width: 70%;"><?= $df->getDisplayValue(); ?></td> - </tr> - <? endforeach; ?> - </tbody> -</table> +<? $data_fields = []; ?> +<? if ($abschnitt_modul) : ?> + <? $data_fields = $abschnitt_modul->datafields->filter( + fn(DatafieldEntryModel $d): bool => ($d->datafield->object_class ?? '') === '') ?> +<? endif; ?> +<? if (count($modulteil_deskriptor->datafields)) : ?> + <table class="mvv-modul-details default nohover" data-mvv-id="<?= $modulteil_deskriptor->id; ?>" data-mvv-type="modulteil_deskriptor"> + <tbody> + <? foreach ($modulteil_deskriptor->datafields as $entry) : ?> + <? if (trim($entry->content)) : ?> + <? $df = $entry->getTypedDatafield(); ?> + <tr> + <td style="width: 30%;"><strong><?= htmlReady($df->getName()) ?></strong></td> + <td style="width: 70%;"><?= $df->getDisplayValue(); ?></td> + </tr> + <? endif; ?> + <? endforeach; ?> + <? foreach ($data_fields as $entry) : ?> + <? if (trim($entry->content)) : ?> + <? $df = $entry->getTypedDatafield(); ?> + <tr> + <td style="width: 30%;"><strong><?= htmlReady($df->getName()) ?></strong></td> + <td style="width: 70%;"><?= $df->getDisplayValue(); ?></td> + </tr> + <? endif; ?> + <? endforeach; ?> + </tbody> + </table> <? endif; ?> diff --git a/app/views/shared/modul/_modullvs.php b/app/views/shared/modul/_modullvs.php index c2fc775..2b45eb1 100644 --- a/app/views/shared/modul/_modullvs.php +++ b/app/views/shared/modul/_modullvs.php @@ -1,3 +1,9 @@ +<?php +/** + * @var Modul $modul + * @var StgteilabschnittModul|null $abschnitt_modul + */ +?> <table class="mvv-modul-details default nohover"> <thead> <tr> @@ -17,48 +23,88 @@ <? $wlPruef = 0; ?> <? $modulSumme = 0; ?> <? $nummer_modulteil = 1; ?> - <? foreach ($modul->modulteile as $modulTeil): ?> - <? $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language ?? null); + <? foreach ($modul->modulteile as $modulteil): ?> + <? $modulteil_deskriptor = $modulteil->getDeskriptor(); // Für die Kenntlichmachung der Modulteile in Listen die Nummer des // Modulteils und den ausgewählten Namen verwenden. // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard- // Bezeichnung verwenden. - if (trim($modulTeil->nummer)) { - $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name']; - $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer); + if (trim($modulteil->nummer)) { + $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name']; + $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulteil->nummer); } else { $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default']; $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name'] . ' ' . $nummer_modulteil; $nummer_modulteil++; } ?> - <? $wlSelbst += $modulTeil->wl_selbst; ?> - <? $wlPruef += $modulTeil->wl_pruef; ?> - <? $modulTeilSumme = $modulTeil->wl_praesenz + $modulTeil->wl_bereitung + $modulTeil->wl_selbst + $modulTeil->wl_pruef; ?> - <? $modulSumme += $modulTeilSumme; ?> + <? $wlSelbst += $modulteil->wl_selbst; ?> + <? $wlPruef += $modulteil->wl_pruef; ?> + <? $modulteil_summe = $modulteil->wl_praesenz + $modulteil->wl_bereitung + $modulteil->wl_selbst + $modulteil->wl_pruef; ?> + <? $modulSumme += $modulteil_summe; ?> <? if (!empty($show_synopse)) : ?> - <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil"> + <tr data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <td data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><strong><?= htmlReady($name_kurz) ?></strong></td> - <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?? '' ?></td> - <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulTeil->sws) ?: '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? sprintf(' (%s)', formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? sprintf(' (%s)',formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?><?= $modulTeil->wl_pruef ?></td> - <td style="text-align: right;"><?= $modulTeilSumme ?></td> + <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?? '' ?></td> + <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulteil_deskriptor->bezeichnung) ?></td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulteil->sws) ?: '' ?></td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"> + <?= $modulteil->wl_praesenz ?> + <?= MVVController::trim($modulteil_deskriptor->kommentar_wl_praesenz) + ? sprintf(' (%s)', formatReady($modulteil_deskriptor->kommentar_wl_praesenz)) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"> + <?= $modulteil->wl_bereitung ?> + <?= MVVController::trim($modulteil_deskriptor->kommentar_wl_bereitung) + ? sprintf(' (%s)', formatReady($modulteil_deskriptor->kommentar_wl_bereitung)) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"> + <?= $modulteil->wl_selbst ?> + <?= MVVController::trim($modulteil_deskriptor->kommentar_wl_selbst) + ? sprintf(' (%s)', formatReady($modulteil_deskriptor->kommentar_wl_selbst)) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"> + <?= $modulteil->wl_pruef ?> + <?= MVVController::trim($modulteil_deskriptor->kommentar_wl_pruef) + ? sprintf(' (%s)',formatReady($modulteil_deskriptor->kommentar_wl_pruef)) + : '' ?> + </td> + <td style="text-align: right;"><?= $modulteil_summe ?></td> </tr> <? else : ?> - <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil"> + <tr data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <td data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><strong><?= htmlReady($name_kurz) ?></strong></td> - <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulTeil->lernlehrform]['name'] ?? '' ?></td> - <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulTeilDeskriptor->bezeichnung) ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulTeil->sws) ?: '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"><?= $modulTeil->wl_praesenz ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_praesenz) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_praesenz)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"><?= $modulTeil->wl_bereitung ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_bereitung) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_bereitung)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"><?= $modulTeil->wl_selbst ?> <?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_selbst) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_selbst)) : '' ?></td> - <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"><?= MVVController::trim($modulTeilDeskriptor->kommentar_wl_pruef) ? tooltipIcon(formatReady($modulTeilDeskriptor->kommentar_wl_pruef)) : '' ?><?= $modulTeil->wl_pruef ?></td> - <td style="text-align: right;"><?= $modulTeilSumme ?></td> + <td data-mvv-field="mvv_modulteil.lernlehrform"><?= $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM']['values'][$modulteil->lernlehrform]['name'] ?? '' ?></td> + <td data-mvv-field="mvv_modulteil_deskriptor.bezeichnung"><?= htmlReady($modulteil_deskriptor->getReplacedValue('bezeichnung')) ?></td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.sws"><?= htmlReady($modulteil->sws) ?: '' ?></td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_praesenz mvv_modulteil_deskriptor.kommentar_wl_praesenz"> + <?= $modulteil->wl_praesenz ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_praesenz')) + ? tooltipIcon(formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_praesenz'))) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_bereitung mvv_modulteil_deskriptor.kommentar_wl_bereitung"> + <?= $modulteil->wl_bereitung ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_bereitung')) + ? tooltipIcon(formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_bereitung'))) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_selbst mvv_modulteil_deskriptor.kommentar_wl_selbst"> + <?= $modulteil->wl_selbst ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_selbst')) + ? tooltipIcon(formatReady($modulteil_deskriptor->getReplacedValue('kommentar_wl_selbst'))) + : '' ?> + </td> + <td style="text-align: right;" data-mvv-field="mvv_modulteil.wl_pruef mvv_modulteil_deskriptor.kommentar_wl_pruef"> + <?= $modulteil->wl_pruef ?> + <?= MVVController::trim($modulteil_deskriptor->getReplacedValue('kommentar_wl_pruef')) + ? tooltipIcon(formatReady($modulteil_deskriptor->kommentar_wl_pruef)) + : '' ?> + </td> + <td style="text-align: right;"><?= $modulteil_summe ?></td> </tr> <? endif; ?> <? endforeach; ?> diff --git a/app/views/shared/modul/_pruefungen.php b/app/views/shared/modul/_pruefungen.php index b5b43cd..47174e7 100644 --- a/app/views/shared/modul/_pruefungen.php +++ b/app/views/shared/modul/_pruefungen.php @@ -1,3 +1,8 @@ +<?php +/** + * @var Modul $modul + */ +?> <table class="mvv-modul-details default nohover"> <thead> <tr> @@ -7,16 +12,16 @@ </tr> </thead> <tbody> - <? foreach ($modul->modulteile as $modulTeil): ?> + <? foreach ($modul->modulteile as $modulteil): ?> <? - $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language ?? null); + $modulteil_deskriptor = $modulteil->getDeskriptor(); // Für die Kenntlichmachung der Modulteile in Listen die Nummer des // Modulteils und den ausgewählten Namen verwenden. - // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard- + // Ist keine Nummer vorhanden, dann durchnummerieren und Standard- // Bezeichnung verwenden. - if (trim($modulTeil->nummer)) { - $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name']; - $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer); + if (trim($modulteil->nummer)) { + $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name']; + $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulteil->nummer); } else { $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default']; $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name'] @@ -24,26 +29,34 @@ $nummer_modulteil++; } ?> - <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil"> + <tr data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <td style="vertical-align: top; font-weight: bold;" data-mvv-field="mvv_modulteil.num_bezeichnung mvv_modulteil.nummer"><?= htmlReady($name_kurz) ?></td> - <td data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"><?= formatReady($modulTeilDeskriptor->pruef_vorleistung) ?></td> - <td data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"><?= formatReady($modulTeilDeskriptor->pruef_leistung) ?></td> - </tr> + <td data-mvv-field="mvv_modulteil_deskriptor.pruef_vorleistung"> + <?= formatReady($modulteil_deskriptor->getReplacedValue('pruef_vorleistung')) ?> + </td> + <td data-mvv-field="mvv_modulteil_deskriptor.pruef_leistung"> + <?= formatReady($modulteil_deskriptor->getReplacedValue('pruef_leistung')) ?> + </td> + </tr> <? endforeach; ?> - <tr data-mvv-id="<?= $modul->getId(); ?>" data-mvv-type="modul"> - <? $modulDeskriptor = $modul->getDeskriptor($display_language) ?> + <tr data-mvv-id="<?= $modul->id; ?>" data-mvv-type="modul"> + <? $deskriptor = $modul->getDeskriptor() ?> <td style="vertical-align: top; font-weight: bold;"> <?= _('Gesamtmodul') ?> </td> - <td data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung"><?= formatReady($modulDeskriptor->pruef_vorleistung) ?></td> - <td data-mvv-field="mvv_modul_deskriptor.pruef_leistung"><?= formatReady($modulDeskriptor->pruef_leistung) ?></td> + <td data-mvv-field="mvv_modul_deskriptor.pruef_vorleistung"> + <?= formatReady($deskriptor->getReplacedValue('pruef_vorleistung')) ?> + </td> + <td data-mvv-field="mvv_modul_deskriptor.pruef_leistung"> + <?= formatReady($deskriptor->getReplacedValue('pruef_leistung')) ?> + </td> </tr> <tr> <td style="vertical-align: top; font-weight: bold;"> <?= _('Wiederholungsprüfung') ?> </td> <td colspan="3"> - <?= formatReady($modulDeskriptor->pruef_wiederholung) ?> + <?= formatReady($deskriptor->getReplacedValue('pruef_wiederholung')) ?> </td> </tr> </tbody> diff --git a/app/views/shared/modul/_regularien.php b/app/views/shared/modul/_regularien.php index 26196b0..0589d0c 100644 --- a/app/views/shared/modul/_regularien.php +++ b/app/views/shared/modul/_regularien.php @@ -1,3 +1,8 @@ +<?php +/** + * @var Modul $modul + */ +?> <table class="mvv-modul-details default nohover"> <thead> <tr> @@ -9,16 +14,16 @@ </tr> </thead> <tbody> - <? foreach ($modul->modulteile as $modulTeil): ?> + <? foreach ($modul->modulteile as $modulteil): ?> <? - $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language); + $modulteil_deskriptor = $modulteil->getDeskriptor(); // Für die Kenntlichmachung der Modulteile in Listen die Nummer des // Modulteils und den ausgewählten Namen verwenden. // Ist keine Nummer vorhanden, dann Durchnummerieren und Standard- // Bezeichnung verwenden. - if (trim($modulTeil->nummer)) { - $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name']; - $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer); + if (trim($modulteil->nummer)) { + $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulteil->num_bezeichnung]['name']; + $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulteil->nummer); } else { $num_bezeichnung_default = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['default']; $name_kurz = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$num_bezeichnung_default]['name'] @@ -26,13 +31,20 @@ $nummer_modulteil++; } ?> - <tr data-mvv-id="<?= $modulTeil->getId(); ?>" data-mvv-type="modulteil"> + <tr data-mvv-id="<?= $modulteil->id; ?>" data-mvv-type="modulteil"> <td style="vertical-align: top; font-weight: bold;" data-mvv-field="mvv_modulteil.nummer mvv_modulteil.num_bezeichnung"><?= $name_kurz ?></td> - <td data-mvv-field="mvv_modulteil_deskriptor.voraussetzung"><?= formatReady($modulTeilDeskriptor->voraussetzung) ?></td> - <td data-mvv-field="mvv_modulteil.semester"><?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulTeil->semester]['name'] ?></td> - <td data-mvv-field="mvv_modulteil.pflicht"><?= ($modulTeil->pflicht ? _('Ja') : _('Nein')) ?> <?= $modulTeilDeskriptor->kommentar_pflicht ? formatReady($modulTeilDeskriptor->kommentar_pflicht) : '' ?></td> - <td data-mvv-field="mvv_modulteil.anteil_note"><?= $modulTeil->anteil_note ?>%</td> - </tr> + <td data-mvv-field="mvv_modulteil_deskriptor.voraussetzung"> + <?= formatReady($modulteil_deskriptor->getReplacedValue('voraussetzung')) ?> + </td> + <td data-mvv-field="mvv_modulteil.semester"> + <?= $GLOBALS['MVV_NAME_SEMESTER']['values'][$modulteil->semester]['name'] ?> + </td> + <td data-mvv-field="mvv_modulteil.pflicht"> + <?= ($modulteil->pflicht ? _('Ja') : _('Nein')) ?> + <?= formatReady($modulteil_deskriptor->getReplacedValue('kommentar_pflicht')) ?> + </td> + <td data-mvv-field="mvv_modulteil.anteil_note"><?= $modulteil->anteil_note ?>%</td> + </tr> <? endforeach; ?> </tbody> -</table>
\ No newline at end of file +</table> diff --git a/app/views/shared/modul/description.php b/app/views/shared/modul/description.php index 758760d..05eddbf 100644 --- a/app/views/shared/modul/description.php +++ b/app/views/shared/modul/description.php @@ -3,6 +3,7 @@ * @var Modul $modul * @var int $type * @var Shared_ModulController $controller + * @var StgteilabschnittModul|null $abschnitt_modul */ ?> @@ -10,7 +11,12 @@ <div style="width: 100%; text-align: right;"> <? foreach ($modul->deskriptoren->getAvailableTranslations($modul->original_language) as $language) : ?> <? $lang = $GLOBALS['CONTENT_LANGUAGES'][$language]; ?> - <a data-dialog="size=auto;title='<?= htmlReady($modul->getDisplayName()) ?>'" href="<?= $controller->action_link('description/' . $modul->id . '/', ['display_language' => $language]) ?>"> + <a data-dialog="size=auto;title='<?= htmlReady($modul->getDisplayName()) ?>'" + href="<?= $controller->action_link('description/' . $modul->id . '/', + [ + 'display_language' => $language, + 'abschnitt_id' => $abschnitt_modul->abschnitt_id, + ]) ?>"> <?= Assets::img(MVV::getContentLanguageImagePath($language), ['alt' => $lang['name'], 'size' => 24]) ?> </a> <? endforeach; ?> diff --git a/app/views/shared/modul/overview.php b/app/views/shared/modul/overview.php index be91c7a..16695bd 100644 --- a/app/views/shared/modul/overview.php +++ b/app/views/shared/modul/overview.php @@ -1,26 +1,32 @@ <?php /** * @var Modul $modul - * @var Institute $institut - * @var ModulDeskriptor $deskriptor - * @var array $modulteile * @var Semester $semester * @var string $pruef_ebene * @var int $type + * @var string $code + * @var string $title */ ?> +<? $deskriptor = $modul->getDeskriptor() ?> <table class="default mvv-modul-details nohover"> <tr> - <th class="mvv-modul-details-head" style="width: 30%"><?= htmlReady($modul->code) ?></th> - <th class="mvv-modul-details-head" style="width: 30%"><?= htmlReady($institut->name) ?></th> - <th class="mvv-modul-details-head" style="width: 40%"><?= sprintf("%d CP", $modul->kp) ?> </th> - <th class="mvv-modul-details-head"></th> + <th class="mvv-modul-details-head" style="width: 30%"> + <?= htmlReady($code ?: $modul->code) ?> + </th> + <th class="mvv-modul-details-head" style="width: 30%"> + <?= $modul->responsible_institute ? htmlReady($modul->responsible_institute->institute->name) : '' ?> + </th> + <th class="mvv-modul-details-head" style="width: 40%"></th> + <th class="mvv-modul-details-head" style="white-space: nowrap;"> + <?= sprintf("%d CP", $modul->getReplacedValue('kp')) ?> + </th> </tr> <tr> <td colspan="2"> - <h3><?= htmlReady($deskriptor->bezeichnung) ?></h3> - <?= _('Lehrveranstaltungen') ?> <?= htmlReady($semester['name']) ?> + <h3><?= htmlReady($title ?: $deskriptor->bezeichnung) ?></h3> + <?= _('Lehrveranstaltungen') ?> <?= htmlReady($semester->name) ?> </td> <td> <dl> @@ -37,8 +43,8 @@ </td> <td> <? if ($GLOBALS['perm']->have_perm('admin')) : ?> - <a href="<?= URLHelper::getLink("dispatch.php/shared/modul/mail/{$modul->id}/{$semester['semester_id']}")?>" data-dialog> - <?= Icon::create('mail', Icon::ROLE_CLICKABLE, tooltip2(_('Nachricht an alle Veranstaltungteilnehmer die diesem Modul zugeordnet sind.')))?> + <a href="<?= URLHelper::getLink("dispatch.php/shared/modul/mail/{$modul->id}/{$semester->id}")?>" data-dialog> + <?= Icon::create('mail', Icon::ROLE_CLICKABLE, tooltip2(_('Nachricht an alle Teilnehmenden der Veranstaltungen, die diesem Modul zugeordnet sind.')))?> </a> <? endif; ?> </td> @@ -46,22 +52,22 @@ <tr> <td colspan="4" style="padding: 0;"> <table class="default nohover"> - <? if (mb_strlen($deskriptor->voraussetzung) > 0): ?> + <? if (mb_strlen($deskriptor->getReplacedValue('voraussetzung')) > 0): ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Teilnahmevoraussetzungen') ?></td> - <td ><?= formatReady($deskriptor->voraussetzung) ?></td> + <td ><?= formatReady($deskriptor->getReplacedValue('voraussetzung')) ?></td> </tr> <? endif; ?> - <? if (mb_strlen($deskriptor->kommentar)) : ?> + <? if (mb_strlen($deskriptor->getReplacedValue('kommentar'))) : ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Hinweise') ?></td> - <td><?= formatReady($deskriptor->kommentar) ?></td> + <td><?= formatReady($deskriptor->getReplacedValue('kommentar')) ?></td> </tr> <? endif; ?> <? if (mb_strlen($deskriptor->ersatztext) > 0): ?> <tr> <td style="width: 20%; font-weight: bold;"> </td> - <td><?= formatReady($deskriptor->ersatztext) ?></td> + <td><?= formatReady($deskriptor->getReplacedValue('ersatztext')) ?></td> </tr> <? else: ?> @@ -70,8 +76,8 @@ <td style="width: 20%; font-weight: bold;"><?= _('Kapazität Modul') ?></td> <td> <?= htmlReady($modul->kapazitaet) ?> - <? if (mb_strlen($deskriptor->kommentar_kapazitaet) > 0): ?> - (<?= formatReady($deskriptor->kommentar_kapazitaet) ?>) + <? if (mb_strlen($deskriptor->getReplacedValue('kommentar_kapazitaet')) > 0): ?> + (<?= formatReady($deskriptor->getReplacedValue('kommentar_kapazitaet')) ?>) <? endif; ?> </td> @@ -83,22 +89,22 @@ <td><?= htmlReady($pruef_ebene) ?></td> </tr> <? endif; ?> - <? if (mb_strlen($deskriptor->pruef_vorleistung)) : ?> + <? if (mb_strlen($deskriptor->getReplacedValue('pruef_vorleistung'))) : ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Prüfungsvorleistung Modul') ?></td> - <td><?= formatReady($deskriptor->pruef_vorleistung) ?></td> + <td><?= formatReady($deskriptor->getReplacedValue('pruef_vorleistung')) ?></td> </tr> <? endif; ?> <? if (mb_strlen($deskriptor->pruef_leistung)) : ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Prüfungsleistung Modul') ?></td> - <td><?= formatReady($deskriptor->pruef_leistung) ?></td> + <td><?= formatReady($deskriptor->getReplacedValue('pruef_leistung')) ?></td> </tr> <? endif; ?> <? if (mb_strlen($deskriptor->kompetenzziele)): ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Kompetenzziele') ?></td> - <td><?= formatReady($deskriptor->kompetenzziele) ?></td> + <td><?= formatReady($deskriptor->getReplacedValue('kompetenzziele')) ?></td> </tr> <? endif; ?> @@ -111,66 +117,62 @@ <? if ($type === 1): ?> <th><?= _('Modulteile') ?></th> <? endif; ?> - <th <? if ($type === 2): ?> colspan="3" <? endif; ?> ><?= _('Semesterveranstaltungen') ?></th> + <th <? if ($type === 2): ?> colspan="4" <? endif; ?> ><?= _('Semesterveranstaltungen') ?></th> <? if ($type === 1): ?> - <th><?= _('Prüfungsleistung') ?></th> + <th colspan="2"><?= _('Prüfungsleistung') ?></th> <? endif; ?> </tr> - <? foreach ($modulteile as $modul_teil): ?> + <? foreach ($modul->modulteile as $modulteil): ?> + <? $modulteil_deskriptor = $modulteil->getDeskriptor() ?> <tr> <? if ($type === 1): ?> <td> - <b> <?= htmlReady($modul_teil['name']) ?> </b> - <? if (mb_strlen($modul_teil['kommentar']) > 0): ?> - <?= $modul_teil['kommentar'] ? '<br>(' . formatReady($modul_teil['kommentar']) . ')' : '' ?> + <b> <?= htmlReady($modulteil_deskriptor->getReplacedValue('bezeichnung')) ?> </b> + <? if (mb_strlen($modulteil_deskriptor->getReplacedValue('kommentar')) > 0): ?> + <?= trim($modulteil_deskriptor->getReplacedValue('kommentar')) ? '<br>(' . formatReady($modulteil_deskriptor->getReplacedValue('kommentar')) . ')' : '' ?> <? endif; ?> - <? if (mb_strlen($modul_teil['voraussetzung']) > 0): ?> + <? if (mb_strlen($modulteil_deskriptor->getReplacedValue('voraussetzung')) > 0): ?> <br> - <b><?= _('Teilnahmevoraussetzungen') ?>:</b> <?= formatReady($modul_teil['voraussetzung']) ?> + <b><?= _('Teilnahmevoraussetzungen') ?>:</b> <?= formatReady($modulteil_deskriptor->getReplacedValue('voraussetzung')) ?> <? endif; ?> </td> <? endif; ?> <td <? if ($type === 2): ?> colspan="3" <? endif; ?>> - <? foreach ($modul_teil['lvGruppen'] as $gruppe): ?> - <? if (mb_strlen($gruppe['alt_texte']) > 0): ?> - <?= formatReady($gruppe['alt_texte']) ?> + <? foreach ($modulteil->lvgruppen as $gruppe): ?> + <? if (mb_strlen($gruppe->alttext) > 0): ?> + <?= formatReady($gruppe->alttext) ?> <? endif; ?> - <? if (count($gruppe['courses'])) : ?> + <? if (count($gruppe->courses)) : ?> <ul> - <? foreach ($gruppe['courses'] as $course): ?> + <? foreach ($gruppe->courses as $course): ?> <li> <a href="<?= URLHelper::getLink('dispatch.php/course/details', ['sem_id' => $course->id]) ?>"> - <?= htmlReady(($course['VeranstaltungsNummer'] ? $course['VeranstaltungsNummer'] . ' - ' : '') . $course['Name']) ?> + <?= htmlReady(($course->veranstaltungsnummer ? $course->veranstaltungsnummer . ' - ' : '') . $course->name) ?> </a> - <? if ($course['visible'] != 1) : ?> + <? if (!$course->visible) : ?> <em><?= _('[versteckt]') ?></em> <? endif; ?> <? if (Config::get()->COURSE_SEARCH_SHOW_ADMISSION_STATE) : ?> <? $admission_status = GlobalSearchCourses::getStatusCourseAdmission($course->id, $course->admission_prelim); ?> - <? switch ($admission_status) : - case 1: - echo Icon::create('span-2quarter', Icon::ROLE_STATUS_YELLOW, [ - 'alt' => _('Eingeschränkter Zugang'), - 'title' => _('Eingeschränkter Zugang'), - 'style' => 'vertical-align: text-bottom', - ]); - break; - case 2: - echo Icon::create('span-empty', Icon::ROLE_STATUS_RED, [ - 'alt' => _('Kein Zugang'), - 'title' => _('Kein Zugang'), - 'style' => 'vertical-align: text-bottom', - ]); - break; - default: - echo Icon::create('span-full', Icon::ROLE_STATUS_GREEN, [ - 'alt' => _('Uneingeschränkter Zugang'), - 'title' => _('Uneingeschränkter Zugang'), - 'style' => 'vertical-align: text-bottom', - ]); - endswitch; ?> + <? echo match ($admission_status) { + 1 => Icon::create('span-2quarter', Icon::ROLE_STATUS_YELLOW, [ + 'alt' => _('Eingeschränkter Zugang'), + 'title' => _('Eingeschränkter Zugang'), + 'style' => 'vertical-align: text-bottom', + ]), + 2 => Icon::create('span-empty', Icon::ROLE_STATUS_RED, [ + 'alt' => _('Kein Zugang'), + 'title' => _('Kein Zugang'), + 'style' => 'vertical-align: text-bottom', + ]), + default => Icon::create('span-full', Icon::ROLE_STATUS_GREEN, [ + 'alt' => _('Uneingeschränkter Zugang'), + 'title' => _('Uneingeschränkter Zugang'), + 'style' => 'vertical-align: text-bottom', + ]), + }; ?> <? endif; ?> </li> <? endforeach; ?> @@ -179,13 +181,13 @@ <? endforeach; ?> </td> <? if ($type === 1) : ?> - <td> - <? if (mb_strlen($modul_teil['pruef_vorleistung']) > 0) : ?> - <b><?= _('Prüfungsvorleistung') ?>:</b> <?= htmlReady($modul_teil['pruef_vorleistung']) ?> + <td colspan="2"> + <? if (mb_strlen($modulteil_deskriptor->getReplacedValue('pruef_vorleistung')) > 0) : ?> + <b><?= _('Prüfungsvorleistung') ?>:</b> <?= htmlReady($modulteil_deskriptor->getReplacedValue('pruef_vorleistung')) ?> <? endif; ?> - <? if (mb_strlen($modul_teil['pruef_leistung']) > 0) : ?> - <b><?= _('Prüfungsform') ?>:</b> <br/><?= htmlReady($modul_teil['pruef_leistung']) ?> (<?= ($modul_teil['anteil_note'] ? '(' . htmlReady($modul_teil['anteil_note']) . '%)' : '') ?> + <? if (mb_strlen($modulteil_deskriptor->pruef_leistung) > 0) : ?> + <b><?= _('Prüfungsform') ?>:</b> <br/><?= htmlReady($modulteil_deskriptor->getReplacedValue('pruef_leistung')) ?> (<?= ($modulteil->anteil_note ? '(' . htmlReady($modulteil->anteil_note) . '%)' : '') ?> <? endif; ?> </td> <? endif; ?> diff --git a/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php b/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php index cd4cd77..a58d09c 100644 --- a/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php +++ b/app/views/studiengaenge/studiengaenge/stgteil_bezeichnungen.php @@ -54,7 +54,7 @@ 'name' => 'search_stgteil', 'data-qs_name' => $search_stgteil->getId(), 'data-qs_id' => $qs_search_stgteil_id, 'data-qs_submit' => 'no', - 'class' => 'mvv-qs-button' + 'class' => 'middle mvv-qs-button' ])->asInput(); ?> </div> <label><?= _('als') ?> @@ -66,7 +66,7 @@ </select> </label> <input type="hidden" name="level" value="stg"> - <input name="add_stgteil" class="text-top mvv-submit" type="image" + <input name="add_stgteil" class="middle mvv-submit" type="image" title="<?= _('Studiengangteil hinzufügen') ?>" src="<?= Icon::create('accept')->asImagePath(); ?>"> </form> diff --git a/app/views/studiengaenge/studiengaenge/studiengaenge.php b/app/views/studiengaenge/studiengaenge/studiengaenge.php index cbfc2cc..0aafb2a 100644 --- a/app/views/studiengaenge/studiengaenge/studiengaenge.php +++ b/app/views/studiengaenge/studiengaenge/studiengaenge.php @@ -22,7 +22,7 @@ <? $ampel_icon = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['icon'] ?? null; ?> <? $ampelstatus = $GLOBALS['MVV_STUDIENGANG']['STATUS']['values'][$studiengang->stat]['name'] ?? null; ?> <? if ($ampel_icon) : ?> - <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?> + <?= $ampel_icon->asImg(['title' => $ampelstatus]) ?> <? endif; ?> <?= htmlReady($studiengang->name) ?> <?= (mb_strlen($studiengang->name_kurz) ? '(' . htmlReady($studiengang->name_kurz) . ')' : '') ?> <? if ($studiengang->count_dokumente) : ?> @@ -33,8 +33,7 @@ 'title' => sprintf( ngettext('%s Dokument zugeordnet', '%s Dokumente zugeordnet', $studiengang->count_dokumente), $studiengang->count_dokumente - ), - 'style' => 'vertical-align: text-top;' + ) ]) ?> <? endif; ?> </a> diff --git a/app/views/studiengaenge/studiengaenge/studiengangteile.php b/app/views/studiengaenge/studiengaenge/studiengangteile.php index 7c3cf92..8efd302 100644 --- a/app/views/studiengaenge/studiengaenge/studiengangteile.php +++ b/app/views/studiengaenge/studiengaenge/studiengangteile.php @@ -76,13 +76,14 @@ 'data-qs_name' => $search->getId(), 'data-qs_id' => $qs_search_id, 'data-qs_submit' => '1', - 'class' => 'mvv-qs-button' + 'class' => 'middle mvv-qs-button' ])->asInput(); ?> <?= Icon::create( 'accept', Icon::ROLE_CLICKABLE , [ - 'title' => _('Studiengangteil zuordnen') + 'title' => _('Studiengangteil zuordnen'), + 'class' => 'middle' ])->asInput(['class' => 'mvv-submit', 'name' => 'add_stgteil']); ?> <? if ($stg_bez) : ?> <input type="hidden" name="stgteil_bez_id" value="<?= $stg_bez->id ?>"> diff --git a/app/views/studiengaenge/versionen/abschnitte.php b/app/views/studiengaenge/versionen/abschnitte.php index 79d3b5a..2d555c7 100644 --- a/app/views/studiengaenge/versionen/abschnitte.php +++ b/app/views/studiengaenge/versionen/abschnitte.php @@ -76,7 +76,7 @@ 'data-qs_name' => $search_modul_version->getId(), 'data-qs_id' => $qs_search_modul_version_id, 'data-qs_submit' => 'no', - 'class' => 'mvv-qs-button' + 'class' => 'middle mvv-qs-button' ]) ?> <label> <?= _('zu Abschnitt') ?> @@ -86,7 +86,7 @@ <? endforeach; ?> </select> </label> - <input name="add_modul" class="text-top mvv-submit" type="image" + <input name="add_modul" class="middle mvv-submit" type="image" title="<?= _('Studiengangteil-Abschnitt hinzufügen') ?>" src="<?= Icon::create('accept')->asImagePath(); ?>"> </form> diff --git a/app/views/studiengaenge/versionen/details_abschnitt.php b/app/views/studiengaenge/versionen/details_abschnitt.php index ed2f293..63abfee 100644 --- a/app/views/studiengaenge/versionen/details_abschnitt.php +++ b/app/views/studiengaenge/versionen/details_abschnitt.php @@ -39,6 +39,9 @@ <?= Icon::create('edit', Icon::ROLE_CLICKABLE , tooltip2(_('Modulzuordnung bearbeiten')))->asImg(); ?> </a> <? endif; ?> + <a data-dialog="size=auto" href="<?= $controller->link_for('module/module/description', $assignment->modul_id, ['abschnitt_id' => $assignment->abschnitt_id]) ?>"> + <?= Icon::create('log', Icon::ROLE_CLICKABLE, tooltip2(_('Lokale Modulbeschreibung')))->asImg(); ?> + </a> <? if (MvvPerm::havePermCreate($assignment)) : ?> <?= Icon::create('trash', Icon::ROLE_CLICKABLE , tooltip2(_('Modulzuordnung löschen'))) ->asInput([ @@ -55,7 +58,11 @@ </tr> <? if (!empty($modul_id) && ($modul_id == $assignment->modul->id)) : ?> <tr class="loaded-details nohover"> - <?= $this->render_partial('studiengaenge/versionen/modulteile', ['modul' => $assignment->modul, 'abschnitt_id' => $assignment->abschnitt_id, 'assignment' => $assignment]) ?> + <?= $this->render_partial('studiengaenge/versionen/modulteile', + [ + 'modul' => $assignment->modul, + 'abschnitt_id' => $assignment->abschnitt_id, + 'assignment' => $assignment]) ?> </tr> <? endif; ?> </tbody> @@ -67,14 +74,23 @@ <?= _('Modul hinzufügen') ?> <?= CSRFProtection::tokenTag() ?> <?= $search_modul_abschnitt->render(); ?> - <?= Icon::create('search', Icon::ROLE_CLICKABLE, ['title' => _('Modul suchen'), 'name' => 'search_stgteil', 'data-qs_name' => $search_modul_abschnitt->getId(), 'data-qs_id' => $qs_search_modul_abschnitt_id, 'data-qs_submit' => 'no', 'class' => 'mvv-qs-button'])->asInput(); ?> + <?= Icon::create('search', Icon::ROLE_CLICKABLE, + [ + 'title' => _('Modul suchen'), + 'name' => 'search_stgteil', + 'data-qs_name' => $search_modul_abschnitt->getId(), + 'data-qs_id' => $qs_search_modul_abschnitt_id, + 'data-qs_submit' => 'no', + 'class' => 'middle mvv-qs-button' + ] + )->asInput(); ?> <input type="hidden" name="abschnitt_id" value="<?= $abschnitt->id ?>"> <?= Icon::create('accept', Icon::ROLE_CLICKABLE , tooltip2(_('Modul hinzufügen'))) ->asInput( [ 'formaction' => $controller->action_url('add_modul', $version->id), 'name' => 'add_modul', - 'class' => 'text-top mvv-submit' + 'class' => 'middle mvv-submit' ] ); ?> </td> diff --git a/app/views/studiengaenge/versionen/modul_zuordnung.php b/app/views/studiengaenge/versionen/modul_zuordnung.php index c2ea20b..bfc4f48 100644 --- a/app/views/studiengaenge/versionen/modul_zuordnung.php +++ b/app/views/studiengaenge/versionen/modul_zuordnung.php @@ -6,7 +6,7 @@ use Studip\Button, Studip\LinkButton; ?> <? $perm = new MvvPerm($zuordnung) ?> -<form class="default" action="<?= $controller->action_link('modul_zuordnung/' . $zuordnung->id) ?>" method="post"> +<form data-dialog="" class="default" action="<?= $controller->action_link('modul_zuordnung_store/' . $zuordnung->id) ?>" method="post"> <?= CSRFProtection::tokenTag() ?> <fieldset> <legend><?= _('Grunddaten') ?></legend> @@ -32,6 +32,21 @@ use Studip\Button, Studip\LinkButton; maxlength="250" value="<?= htmlReady($zuordnung->modulcode) ?>"> </label> </fieldset> + <? if (count($zuordnung->datafields)) : ?> + <fieldset> + <legend><?= _('Angaben zum Modul am Studiengangteilabschnitt') ?></legend> + <? $default_language = array_keys($GLOBALS['CONTENT_LANGUAGES'])[0] ?> + <? foreach ($zuordnung->datafields as $entry) : ?> + <? $tdf = $entry->getTypedDatafield(); ?> + <? if ($perm->haveDfEntryPerm($entry->datafield_id, MvvPerm::PERM_WRITE)) : ?> + <?= $tdf->getHTML('datafields') ?> + <? else : ?> + <em><?= htmlReady($tdf->getName()) ?>:</em><br> + <?= $tdf->getDisplayValue() ?> + <? endif; ?> + <? endforeach; ?> + </fieldset> + <? endif; ?> <footer data-dialog-button> <?= Button::createAccept( _('Übernehmen'), diff --git a/app/views/studiengaenge/versionen/modulteil_semester.php b/app/views/studiengaenge/versionen/modulteil_semester.php index 86648f5..383b76c 100644 --- a/app/views/studiengaenge/versionen/modulteil_semester.php +++ b/app/views/studiengaenge/versionen/modulteil_semester.php @@ -2,21 +2,19 @@ /** * @var Studiengaenge_VersionenController $controller * @var StgteilabschnittModul $abschnitt_modul + * @var Modulteil $modulteil + * @var ModulteilStgteilabschnitt $assignment */ use Studip\Button, Studip\LinkButton; $perm_abschnitt = MvvPerm::getFieldPermModulteil_abschnitte($abschnitt_modul->abschnitt); ?> - -<h3> - <?= _('Zuordnung der Modulteile zu Fachsemestern') ?> -</h3> <form class="default" data-dialog="" action="<?= $controller->action_link('modulteil_semester', $abschnitt_modul->id, $modulteil->id) ?>" method="post"> <?= CSRFProtection::tokenTag() ?> - <fieldset> + <? $perm = MvvPerm::get($assignment) ?> + <fieldset class="collapsable"> <legend><?= _('Belegung in folgenden Fachsemestern') ?></legend> <? for ($i = 1; $i <= $GLOBALS['MVV_MODULTEIL_FACHSEMESTER']; $i++) : ?> <? $fachsemester = $abschnitt_modul->getFachsemester($modulteil->id, $i) ?> - <? $perm = $fachsemester ? MvvPerm::get($fachsemester) : null ?> <div class="mvv-fachsemester" style="flex:1;"> <label> <? if ($fachsemester) : ?> @@ -39,21 +37,31 @@ $perm_abschnitt = MvvPerm::getFieldPermModulteil_abschnitte($abschnitt_modul->ab <?= $GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'][$fachsemester->differenzierung]['name'] ?> <input type="hidden" name="status[<?= $i ?>]" value="<?= $fachsemester->differenzierung ?>"> <? else: ?> - <select name="status[<?= $i ?>]"> - <option value="">-- <?= _('Bitte wählen') ?> --</option> - <? foreach ($GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'] as $status_key => $status) : ?> - <? if ($status['visible']) : ?> - <option value="<?= $status_key ?>"<?= ($fachsemester && $fachsemester->differenzierung == $status_key ? ' selected' : '') ?>><?= $status['name'] ?></option> - <? endif; ?> - <? endforeach; ?> - </select> - - + <select name="status[<?= $i ?>]"> + <option value="">-- <?= _('Bitte wählen') ?> --</option> + <? foreach ($GLOBALS['MVV_MODULTEIL_STGABSCHNITT']['STATUS']['values'] as $status_key => $status) : ?> + <? if ($status['visible']) : ?> + <option value="<?= $status_key ?>"<?= ($fachsemester && $fachsemester->differenzierung == $status_key ? ' selected' : '') ?>><?= $status['name'] ?></option> + <? endif; ?> + <? endforeach; ?> + </select> <? endif; ?> </label> </div> <? endfor; ?> </fieldset> + <fieldset class="collapsable"> + <legend><?= _('Angaben zum Modulteil am Studiengangteilabschnitt') ?></legend> + <? foreach ($assignment->datafields as $entry) : ?> + <? $tdf = $entry->getTypedDatafield(); ?> + <? if ($perm->haveDfEntryPerm($entry->datafield_id, MvvPerm::PERM_WRITE)) : ?> + <?= $tdf->getHTML('datafields') ?> + <? else : ?> + <em><?= htmlReady($tdf->getName()) ?>:</em><br> + <?= $tdf->getDisplayValue() ?> + <? endif; ?> + <? endforeach; ?> + </fieldset> <div data-dialog-button > <? if ($perm_abschnitt >= MvvPerm::PERM_WRITE) : ?> <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?> diff --git a/app/views/studiengaenge/versionen/versionen.php b/app/views/studiengaenge/versionen/versionen.php index aff5d5f..27a75ae 100644 --- a/app/views/studiengaenge/versionen/versionen.php +++ b/app/views/studiengaenge/versionen/versionen.php @@ -9,7 +9,7 @@ <? $ampel_icon = $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['icon'] ?> <? $ampelstatus = $GLOBALS['MVV_STGTEILVERSION']['STATUS']['values'][$version->stat]['name'] ?> <? if ($ampel_icon) : ?> - <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?> + <?= $ampel_icon->asImg(['title' => $ampelstatus]) ?> <? endif; ?> <?= htmlReady($version->getDisplayName()) ?> <? if ($version->count_abschnitte) : ?> diff --git a/db/migrations/6.0.51_step5383_new_data_field_types_for_mvv.php b/db/migrations/6.0.51_step5383_new_data_field_types_for_mvv.php new file mode 100644 index 0000000..537b71c --- /dev/null +++ b/db/migrations/6.0.51_step5383_new_data_field_types_for_mvv.php @@ -0,0 +1,29 @@ +<?php +final class Step5383NewDataFieldTypesForMvv extends Migration +{ + public function description() + { + return 'Adds new data field types related to StgteilAbschnitModul and ModulteilStgteilAbschnitt objects'; + } + + public function up() + { + $query = "ALTER TABLE `datafields` + CHANGE `object_type` `object_type` ENUM('sem','inst','user', + 'userinstrole','usersemdata','roleinstdata','moduldeskriptor', + 'modulteildeskriptor','studycourse', + 'stgteilabschnittmodul','modulteilstgteilabschnitt') + NULL DEFAULT NULL"; + DBManager::get()->exec($query); + } + + public function down() + { + $query = "ALTER TABLE `datafields` + CHANGE `object_type` `object_type` ENUM('sem','inst','user', + 'userinstrole','usersemdata','roleinstdata','moduldeskriptor', + 'modulteildeskriptor','studycourse') + NULL DEFAULT NULL"; + DBManager::get()->exec($query); + } +} diff --git a/lib/classes/I18NStringDatafield.php b/lib/classes/I18NStringDatafield.php index 6007872..942064d 100644 --- a/lib/classes/I18NStringDatafield.php +++ b/lib/classes/I18NStringDatafield.php @@ -77,7 +77,7 @@ class I18NStringDatafield extends I18NString /** * Returns an I18NString object by given object_id, table and field. * - * @param string $object_id The id of the object with i18n fields. + * @param string|array $object_id The id of the object with i18n fields. * @param string $table The name of the table with the original values. * @param string $field The name of the i18n field. * @param string $base Sets the original value or retrieve it from database diff --git a/lib/classes/MvvReplaceDataFieldsTrait.php b/lib/classes/MvvReplaceDataFieldsTrait.php new file mode 100644 index 0000000..fe0d5e6 --- /dev/null +++ b/lib/classes/MvvReplaceDataFieldsTrait.php @@ -0,0 +1,90 @@ +<?php +trait MvvReplaceDataFieldsTrait +{ + /** + * The id of the section (Studiengangteil-Abschnitt) with replaced or + * added fields (defined as data fields) in all related objects. + * + * @var string|null $replace_df_abschnitt_id + */ + private string|null $replace_df_abschnitt_id = null; + + /** + * Set the section (Studiengangteil-Abschnitt) with replaced or + * added fields (defined as data fields) for all related objects. + * + * @param Stgteilabschnitt $abschnitt The section. + * @return int The number of objects related to the given section. + */ + public function setReplaceDfAbschnitt(Stgteilabschnitt $abschnitt): int + { + $this->replace_df_abschnitt_id = $abschnitt->id; + return 1; + } + + /** + * Returns the replaced value for the given field and section id. + * + * @param string $field + * @param string|null $abschnitt_id + * @return string + */ + public function getReplacedValue( + string $field, + string $abschnitt_id = null + ): string + { + $abschnitt_id = $abschnitt_id ?? $this->replace_df_abschnitt_id; + if (is_null($abschnitt_id)) { + return $this->getValue($field) ?? ''; + } + + if (!in_array($field, array_keys(static::db_fields()))) { + throw new InvalidArgumentException(static::class . '::' . $field . ' not found.'); + } + // find data field that replaces the given local field + $data_field_id = static::getReplaceDataFieldsId($field, $this->abschnitt_assignments->getClassName()); + if ($data_field_id) { + $abschnitt = $this->abschnitt_assignments->findOneBy('abschnitt_id', $abschnitt_id); + if (!$abschnitt) { + return $this->getValue($field) ?? ''; + } + $data_field = $abschnitt->datafields->findOneBy('datafield_id', $data_field_id); + if (mb_strlen($data_field->getValue('content'))) { + $tdf = $data_field->getTypedDatafield(); + return $tdf->getDisplayValue(); + } + } + return $this->getValue($field) ?? ''; + } + + /** + * Retrieves the id of the related data field. + * + * @param string $field The field to search for a related data field. + * @param string $related_class The name of the related class. + * @return string|null The id of the data field. Null if no related data field. + */ + private static function getReplaceDataFieldsId( + string $field, + string $related_class + ): string|null + { + static $data_fields = null; + + if (is_null($data_fields)) { + DataField::findEachBySQL( + function (DataField $f) use (&$data_fields) { + $data_fields[$f->object_class] = $f->datafield_id; + }, + "`object_type` = ? AND `object_class` IN(?)", + [ + strtolower($related_class), + array_keys(static::db_fields()) + ] + ); + $data_fields = $data_fields ?: []; + } + return $data_fields[$field] ?? null; + } +} diff --git a/lib/models/DataField.php b/lib/models/DataField.php index fa2ba0b..a4b6f95 100644 --- a/lib/models/DataField.php +++ b/lib/models/DataField.php @@ -126,15 +126,17 @@ class DataField extends SimpleORMap implements PrivacyObject public static function getDataClass() { return [ - 'sem' => _('Veranstaltungen'), - 'inst' => _('Einrichtungen'), - 'user' => _('Benutzer'), - 'userinstrole' => _('Benutzerrollen in Einrichtungen'), - 'usersemdata' => _('Benutzer-Zusatzangaben in VA'), - 'roleinstdata' => _('Rollen in Einrichtungen'), - 'moduldeskriptor' => _('Moduldeskriptoren'), - 'modulteildeskriptor' => _('Modulteildeskriptoren'), - 'studycourse' => _('Studiengänge') + 'sem' => _('Veranstaltungen'), + 'inst' => _('Einrichtungen'), + 'user' => _('Benutzer'), + 'userinstrole' => _('Benutzerrollen in Einrichtungen'), + 'usersemdata' => _('Benutzer-Zusatzangaben in VA'), + 'roleinstdata' => _('Rollen in Einrichtungen'), + 'moduldeskriptor' => _('Moduldeskriptoren'), + 'modulteildeskriptor' => _('Modulteildeskriptoren'), + 'studycourse' => _('Studiengänge'), + 'stgteilabschnittmodul' => _('Module an Studiengangteilabschnitten'), + 'modulteilstgteilabschnitt' => _('Modulteile an Studiengangteilabschnitten'), ]; } @@ -285,4 +287,6 @@ class DataField extends SimpleORMap implements PrivacyObject } } } + + } diff --git a/lib/models/DatafieldEntryModel.php b/lib/models/DatafieldEntryModel.php index 408fe33..c19d9f9 100644 --- a/lib/models/DatafieldEntryModel.php +++ b/lib/models/DatafieldEntryModel.php @@ -117,6 +117,17 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject $object_class = $model->getVariant(); $object_type = 'studycourse'; $range_id = $model->studiengang_id; + } elseif ($model instanceof StgteilabschnittModul) { + $params[':institution_ids'] = []; + $object_class = ''; + $object_type = 'stgteilabschnittmodul'; + $range_id = $model->abschnitt_modul_id; + } elseif ($model instanceof ModulteilStgteilabschnitt) { + $params[':institution_ids'] = []; + $object_class = ''; + $object_type = 'modulteilstgteilabschnitt'; + $range_id = $model->modulteil_id; + $sec_range_id = $model->abschnitt_id; } else { throw new InvalidArgumentException('Wrong type of model: ' . get_class($model)); } @@ -155,11 +166,20 @@ class DatafieldEntryModel extends SimpleORMap implements PrivacyObject || $object_type === 'modulteildeskriptor') { // find datafields by language (string) $query .= " AND (LOCATE(:object_class, object_class) OR object_class IS NULL) ORDER BY priority"; - $params = array_merge($params,[ - ':range_id' => (string) $range_id, - ':sec_range_id' => (string) $sec_range_id, - ':object_type' => $object_type, - ':object_class' => (string) $object_class, + $params = array_merge($params, [ + ':range_id' => (string)$range_id, + ':sec_range_id' => (string)$sec_range_id, + ':object_type' => $object_type, + ':object_class' => (string)$object_class, + ]); + } elseif ($object_type === 'stgteilabschnittmodul' + || $object_type === 'modulteilstgteilabschnitt') { + // field object_class holds the name of the overwritten field or is null + $query .= " ORDER BY priority"; + $params = array_merge($params, [ + ':range_id' => (string)$range_id, + ':sec_range_id' => (string)$sec_range_id, + ':object_type' => $object_type, ]); } else { // find datafields by perms or status (int) diff --git a/lib/models/Modul.php b/lib/models/Modul.php index 8c90e18..3c79ef9 100644 --- a/lib/models/Modul.php +++ b/lib/models/Modul.php @@ -60,6 +60,8 @@ class Modul extends ModuleManagementModelTreeItem { + use MvvReplaceDataFieldsTrait; + protected static function configure($config = []) { $config['db_table'] = 'mvv_modul'; @@ -141,15 +143,14 @@ class Modul extends ModuleManagementModelTreeItem 'on_store' => 'store' ]; - $config['additional_fields']['count_modulteile']['get'] = function ($modul) { - return $modul->count_modulteile; - }; - $config['additional_fields']['languagesofinstruction']['get'] = function ($modul) { - return $modul->languages; - }; - $config['additional_fields']['display_name']['get'] = function ($modul) { - return $modul->getDisplayName(); - }; + $config['additional_fields']['count_modulteile']['get'] = + fn(Modul $modul): int => $modul->count_modulteile; + $config['additional_fields']['languagesofinstruction']['get'] = + fn(Modul $modul): SimpleORMapCollection => $modul->languages; + $config['additional_fields']['display_name']['get'] = + fn(Modul $modul): string => $modul->getDisplayName(); + $config['additional_fields']['abschnitt_assignments']['get'] = + fn(Modul $modul): SimpleORMapCollection => $modul->abschnitte_modul; $config['alias_fields']['flexnow_id'] = 'flexnow_modul'; @@ -1034,4 +1035,21 @@ class Modul extends ModuleManagementModelTreeItem } return $courses; } + + /** + * Set the section (Studiengangteil-Abschnitt) with replaced or + * added fields (defined as data fields) for all related objects. + * + * @param Stgteilabschnitt $abschnitt The section. + * @return int The number of objects related to the given section. + * @see MvvReplaceDataFieldsTrait::setReplaceDfAbschnitt() + */ + public function setReplaceDfAbschnitt(Stgteilabschnitt $abschnitt): int + { + $this->replace_df_abschnitt_id = $abschnitt->id; + $ret = $this->modulteile->each(fn(Modulteil $mt): int => $mt->setReplaceDfAbschnitt($abschnitt)); + $ret += $this->deskriptoren->setReplaceDfAbschnitt($abschnitt); + return $ret + 1; + } + } diff --git a/lib/models/ModulDeskriptor.php b/lib/models/ModulDeskriptor.php index d9da0bb..fe41200 100644 --- a/lib/models/ModulDeskriptor.php +++ b/lib/models/ModulDeskriptor.php @@ -44,6 +44,8 @@ class ModulDeskriptor extends ModuleManagementModel { + use MvvReplaceDataFieldsTrait; + protected static function configure($config = []) { $config['db_table'] = 'mvv_modul_deskriptor'; @@ -69,6 +71,9 @@ class ModulDeskriptor extends ModuleManagementModel } ]; + $config['additional_fields']['abschnitt_assignments']['get'] = + fn(ModulDeskriptor $m): SimpleORMapCollection => $m->modul->abschnitte_modul; + $config['i18n_fields']['verantwortlich'] = true; $config['i18n_fields']['bezeichnung'] = true; $config['i18n_fields']['voraussetzung'] = true; diff --git a/lib/models/Modulteil.php b/lib/models/Modulteil.php index 541d301..07ba2cc 100644 --- a/lib/models/Modulteil.php +++ b/lib/models/Modulteil.php @@ -48,6 +48,8 @@ class Modulteil extends ModuleManagementModelTreeItem { + use MvvReplaceDataFieldsTrait; + protected static function configure($config = []) { $config['db_table'] = 'mvv_modulteil'; @@ -321,7 +323,7 @@ class Modulteil extends ModuleManagementModelTreeItem /** * Assignes languages of instruction to this part-module. * - * @param type $languages An array of language keys defined in mvv_config.php. + * @param string[] $languages An array of language keys defined in mvv_config.php. */ public function assignLanguagesOfInstruction($languages) { @@ -396,4 +398,17 @@ class Modulteil extends ModuleManagementModelTreeItem return $courses; } + /** + * Set the section (Studiengangteil-Abschnitt) with replaced or + * added fields (defined as data fields) for all related objects. + * + * @param Stgteilabschnitt $abschnitt The section. + * @return int The number of objects related to the given section. + * @see MvvReplaceDataFieldsTrait::setReplaceDfAbschnitt() + */ + public function setReplaceDfAbschnitt(StgteilAbschnitt $abschnitt): int + { + $this->replace_df_abschnitt_id = $abschnitt->id; + return $this->deskriptoren->setReplaceDfAbschnitt($abschnitt) + 1; + } } diff --git a/lib/models/ModulteilDeskriptor.php b/lib/models/ModulteilDeskriptor.php index eaf41a5..221ef73 100644 --- a/lib/models/ModulteilDeskriptor.php +++ b/lib/models/ModulteilDeskriptor.php @@ -37,6 +37,8 @@ class ModulteilDeskriptor extends ModuleManagementModel { + use MvvReplaceDataFieldsTrait; + protected static function configure($config = []) { $config['db_table'] = 'mvv_modulteil_deskriptor'; @@ -62,6 +64,9 @@ class ModulteilDeskriptor extends ModuleManagementModel } ]; + $config['additional_fields']['abschnitt_assignments']['get'] = + fn(ModulteilDeskriptor $md): SimpleORMapCollection => $md->modulteil->abschnitt_assignments; + $config['i18n_fields']['bezeichnung'] = true; $config['i18n_fields']['voraussetzung'] = true; $config['i18n_fields']['kommentar'] = true; diff --git a/lib/models/ModulteilStgteilabschnitt.php b/lib/models/ModulteilStgteilabschnitt.php index d16c3a0..0b34468 100644 --- a/lib/models/ModulteilStgteilabschnitt.php +++ b/lib/models/ModulteilStgteilabschnitt.php @@ -43,6 +43,20 @@ class ModulteilStgteilabschnitt extends ModuleManagementModel 'foreign_key' => 'abschnitt_id', 'assoc_func' => 'findCached', ]; + $config['has_many']['datafields'] = [ + 'class_name' => DatafieldEntryModel::class, + 'assoc_foreign_key' => + function($model, $params) { + $model->setValue('range_id', $params[0]->id); + }, + 'assoc_func' => 'findByModel', + 'on_delete' => 'delete', + 'on_store' => 'store', + 'foreign_key' => + function($m) { + return [$m]; + } + ]; parent::configure($config); } diff --git a/lib/models/StgteilVersion.php b/lib/models/StgteilVersion.php index 017b590..9cb4b00 100644 --- a/lib/models/StgteilVersion.php +++ b/lib/models/StgteilVersion.php @@ -355,26 +355,39 @@ class StgteilVersion extends ModuleManagementModelTreeItem // TODO set default value $new_version->stat = 'planung'; $new_mvv_objects[] = $new_version; - foreach (StgteilAbschnitt::findByStgteilVersion($this->getId()) as $abschnitt) { + foreach ($this->abschnitte as $abschnitt) { $new_abschnitt = clone $abschnitt; $new_abschnitt->setNew(true); $new_abschnitt->setNewId(); $new_abschnitt->version_id = $new_version->version_id; $new_mvv_objects[] = $new_abschnitt; - $modul_assignments = $abschnitt->getModulAssignments(); - foreach ($modul_assignments as $assignment) { + foreach ($abschnitt->modul_zuordnungen as $assignment) { $new_modul_assignment = clone $assignment; $new_modul_assignment->setNew(true); $new_modul_assignment->setNewId(); $new_modul_assignment->abschnitt_id = $new_abschnitt->abschnitt_id; + // copy data fields + foreach ($assignment->datafields as $datafield) { + $new_data_field = clone $datafield; + $new_data_field->setNew(true); + $new_data_field->range_id = $new_modul_assignment->abschnitt_modul_id; + $new_mvv_objects[] = $new_data_field; + } $new_mvv_objects[] = $new_modul_assignment; } - $modulteil_assignments = ModulteilStgteilabschnitt::findBySql( - 'abschnitt_id = ' . DBManager::get()->quote($abschnitt->getId())); - foreach ($modulteil_assignments as $assignment) { + foreach ($abschnitt->modulteil_abschnitte as $assignment) { $new_modulteil_assignment = clone $assignment; $new_modulteil_assignment->setNew(true); $new_modulteil_assignment->abschnitt_id = $new_abschnitt->abschnitt_id; + // copy data fields + if (empty($assignment->fachsemester)) { + foreach ($assignment->datafields as $datafield) { + $new_data_field = clone $datafield; + $new_data_field->setNew(true); + $new_data_field->sec_range_id = $new_abschnitt->abschnitt_id; + $new_mvv_objects[] = $new_data_field; + } + } $new_mvv_objects[] = $new_modulteil_assignment; } } diff --git a/lib/models/StgteilabschnittModul.php b/lib/models/StgteilabschnittModul.php index d871df6..aa0eba7 100644 --- a/lib/models/StgteilabschnittModul.php +++ b/lib/models/StgteilabschnittModul.php @@ -28,6 +28,7 @@ * @property int $chdate database column * @property Modul $modul belongs_to Modul * @property StgteilAbschnitt $abschnitt belongs_to StgteilAbschnitt + * @property DataField $datafield has_many DataField */ class StgteilabschnittModul extends ModuleManagementModelTreeItem @@ -46,6 +47,20 @@ class StgteilabschnittModul extends ModuleManagementModelTreeItem 'foreign_key' => 'abschnitt_id', 'assoc_func' => 'findCached', ]; + $config['has_many']['datafields'] = [ + 'class_name' => DatafieldEntryModel::class, + 'assoc_foreign_key' => + function($model, $params) { + $model->setValue('range_id', $params[0]->id); + }, + 'assoc_func' => 'findByModel', + 'on_delete' => 'delete', + 'on_store' => 'store', + 'foreign_key' => + function($m) { + return [$m]; + } + ]; $config['i18n_fields']['bezeichnung'] = true; @@ -135,9 +150,15 @@ class StgteilabschnittModul extends ModuleManagementModelTreeItem { $ret = []; $modulteil_abschnitte = ModulteilStgteilabschnitt::findBySql( - 'modulteil_id = ' . DBManager::get()->quote($modulteil_id) - . ' AND abschnitt_id = ' - . DBManager::get()->quote($this->abschnitt_id)); + '`modulteil_id` = ? + AND `abschnitt_id` = ? + AND `fachsemester` > 0 + ORDER BY `fachsemester` ASC', + [ + $modulteil_id, + $this->abschnitt_id, + ] + ); foreach ($modulteil_abschnitte as $modulteil_abschnitt) { $ret[$modulteil_abschnitt->fachsemester] = $modulteil_abschnitt; } diff --git a/resources/assets/javascripts/mvv.js b/resources/assets/javascripts/mvv.js index c00567d..9191ad7 100644 --- a/resources/assets/javascripts/mvv.js +++ b/resources/assets/javascripts/mvv.js @@ -227,14 +227,16 @@ STUDIP.MVV.Search = { qs_real = qs_input.prev('input'), qs_name = qs_input.attr('id'), qs_select = jQuery('<select/>').attr('id', 'select_' + qs_name) - .addClass('mvv-search-select-list'), + .addClass('mvv-search-select-list') + .css({display: 'inline'}), qs_id = qs_item.data('qs_id'), do_submit = qs_item.data('qs_submit'); var reset_button = jQuery('<input type="image" />'); reset_button.attr({ src: STUDIP.ASSETS_URL+'images/icons/blue/decline.svg', title: $gettext("Suche zurücksetzen") - }).addClass('mvv-search-reset'); + }).addClass('mvv-search-reset middle') + .css({display: 'inline'}); if (!_.isUndefined(do_submit)) { qs_select.change(function() { var selected = qs_select.children('option:selected'); |
