diff --git a/app/controllers/materialien/files.php b/app/controllers/materialien/files.php index 25fd5b28ee9af81bd2767af3ae3c2a235a0ddbce..a8d4823d543b4ac3df169613710325e4b142ed21 100644 --- a/app/controllers/materialien/files.php +++ b/app/controllers/materialien/files.php @@ -147,7 +147,7 @@ class Materialien_FilesController extends MVVController CSRFProtection::verifyUnsafeRequest(); $stored = false; - foreach($GLOBALS['MVV_LANGUAGES']['values'] as $key => $entry) { + foreach($GLOBALS['CONTENT_LANGUAGES'] as $key => $entry) { if (Request::get('doc_url_'.$key)) { $file = $this->upload_fileurl($mvvfile_id, Request::get('doc_url_'.$key)); if ($file) { diff --git a/app/controllers/module/download.php b/app/controllers/module/download.php index be527d5747ebf48b258c5f312bc50c76410ae8a7..e5f5be836b740ae038fe78af3bdd9a66d2f55a7e 100644 --- a/app/controllers/module/download.php +++ b/app/controllers/module/download.php @@ -10,14 +10,15 @@ class Module_DownloadController extends MVVController public function details_action($modul_id, $language = null) { - $language = Request::get('display_language', $language); - ModuleManagementModel::setLanguage($language); - $modul = Modul::find($modul_id); if (!$modul) { throw new Exception(_('Ungültiges Modul')); } - $this->getDetails($modul_id, $language); + $language = Request::get('display_language', $language) ?? $modul->original_language; + I18NString::setDefaultLanguage($modul->original_language); + I18NString::setContentLanguage($language); + + $this->getDetails($modul_id); $this->download = true; $as_pdf = Request::int('pdf'); @@ -51,7 +52,7 @@ class Module_DownloadController extends MVVController } } - private function getDetails($id, $language = null) + private function getDetails($id) { $modul = Modul::find($id); if (!$modul) { @@ -81,7 +82,7 @@ class Module_DownloadController extends MVVController $modulTeilData = []; foreach ($modul->modulteile as $modulTeil) { - $deskriptor = $modulTeil->getDeskriptor($language); + $deskriptor = $modulTeil->getDeskriptor(); $num_bezeichnung = $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG']['values'][$modulTeil->num_bezeichnung]['name'] ?? ''; $name_kurz = sprintf('%s %d', $num_bezeichnung, $modulTeil->nummer); @@ -134,7 +135,7 @@ class Module_DownloadController extends MVVController $this->semesterSelector = Semester::GetSemesterSelector(null, $currentSemester->getId(), 'semester_id', false); $this->modul = $modul; $this->pruefungsEbene = $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->pruef_ebene]['name'] ?? null; - $this->modulDeskriptor = $modul->getDeskriptor($language); + $this->modulDeskriptor = $modul->getDeskriptor(); $this->startSemester = Semester::find($modul->start); if ($modul->responsible_institute->institute) { $this->instituteName = $modul->responsible_institute->getDisplayName(); diff --git a/app/controllers/module/module.php b/app/controllers/module/module.php index 10674d07dc916d8ded6d027efa57f00cc72bdf0d..08597f1cacb1e383d52a979195290b75257ef2e4 100644 --- a/app/controllers/module/module.php +++ b/app/controllers/module/module.php @@ -15,7 +15,10 @@ class Module_ModuleController extends MVVController { parent::before_filter($action, $args); // set navigation - Navigation::activateItem($this->me . '/module/module'); + Navigation::getItem('mvv/module/module') + ->setActive(static::class === Module_ModuleController::class); + Navigation::getItem('mvv/module/institutes') + ->setActive(static::class === Module_InstituteController::class); $this->filter = $this->sessGet('filter', []); $this->action = $action; $this->modul_id = ''; @@ -105,6 +108,14 @@ class Module_ModuleController extends MVVController $this->setSidebar(); } + public function select_module_language_action() + { + $this->content_languages = $GLOBALS['CONTENT_LANGUAGES']; + $this->default_language = Config::get()->MVV_DEFAULT_LANGUAGE; + PageLayout::setTitle(_('Ausgabeprache wählen')); + $this->render_template('module/module/select_module_language'); + } + public function modul_action($modul_id = null, $institut_id = null) { $own_institutes = MvvPerm::getOwnInstitutes(); @@ -133,13 +144,20 @@ class Module_ModuleController extends MVVController if ($this->modul->isNew()) { PageLayout::setTitle(_('Neues Modul anlegen')); $success_message = ('Das Modul "%s" wurde angelegt.'); - $this->display_language = $this->modul->getDefaultLanguage(); - $this->deskriptor = $this->modul->getDeskriptor($this->display_language, true); + $language = Request::option('display_language'); + $content_languages = $GLOBALS['CONTENT_LANGUAGES']; + if (!empty($content_languages[$language])) { + $this->display_language = $language; + } else { + $this->display_language = Config::get()->MVV_DEFAULT_LANGUAGE; + } + $this->modul->original_language = $this->display_language; + $this->deskriptor = $this->modul->getDeskriptor(); $this->reset_search('Modul'); if (!$modul_id) { PageLayout::postInfo(sprintf( - _('Sie legen ein neues Modul an. Das Modul muss zunächst in der Ausgabesprache <em>%s</em> angelegt werden.'), - $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['name'] + _('Sie legen ein neues Modul an. Das Modul wird zunächst in der Ausgabesprache <em>%s</em> angelegt (Originalsprache).'), + $GLOBALS['CONTENT_LANGUAGES'][$this->display_language]['name'] )); } // set default language of instruction @@ -151,39 +169,37 @@ class Module_ModuleController extends MVVController } else { $this->display_language = Request::option( 'display_language', - $this->modul->getDefaultLanguage() + $this->modul->original_language ); - $this->deskriptor = $this->modul->getDeskriptor($this->display_language, true); - $this->translations = $this->deskriptor->getAvailableTranslations(); + $this->deskriptor = $this->modul->getDeskriptor(); + $this->translations = $this->deskriptor->getAvailableTranslations($this->modul->original_language); + $content_languages = $GLOBALS['CONTENT_LANGUAGES']; if (!in_array($this->display_language, $this->translations)) { - PageLayout::setTitle( + PageLayout::postInfo( sprintf( - _('Modul: <em>%s</em> in der Ausgabesprache <em>%s</em> neu anlegen.'), + _('Modul: <em>%1$s</em> in der Ausgabesprache <em>%2$s</em> neu anlegen.'), $this->modul->getDisplayName(), - $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['name'] + $content_languages[$this->display_language]['name'] ) ); - } else { - PageLayout::setTitle(sprintf( - _('Modul: %s bearbeiten'), $this->modul->getDisplayName() - )); } $success_message = _('Das Modul "%s" wurde geändert.'); - // language selector as sidebar widget - $template_factory = $this->get_template_factory(); - $sidebar_template = $template_factory->render('shared/deskriptor_language', [ - 'modul' => $this->modul, - 'sprache' => $this->display_language, - 'link' => $this->modulURL($this->modul->id, $this->institut_id), - 'url' => $this->url] - ); - - $widget = new SidebarWidget(); - $widget->setTitle(_('Ausgabesprache')); - $widget->addElement(new WidgetElement($sidebar_template)); - $sidebar->addWidget($widget, 'language'); + $views_widget = new ViewsWidget(); + $views_widget->setTitle(_('Ausgabesprache')); + $languages = $this->translations; + $content_languages = array_merge(array_flip($languages), $GLOBALS['CONTENT_LANGUAGES']); + foreach ($content_languages as $code => $language) { + $views_widget->addLink($language['name'] + . ' (' . ($code === $this->modul->original_language ? _('Originalfassung') . ', ' : '') + . (in_array($code, $languages) ? _('bearbeiten') : _('neu anlegen')) . ')', + URLHelper::getLink($this->modulURL($this->modul->id, $this->institut_id), + ['display_language' => $code] + ) + )->setActive($code === $this->display_language); + } + $sidebar->insertWidget($views_widget, 'actions','language'); $action_widget = $sidebar->getWidget('actions'); $action_widget->addLink( @@ -223,21 +239,22 @@ class Module_ModuleController extends MVVController // list all variants $variants = $this->modul->getVariants(); if (count($variants)) { - $widget = new SidebarWidget(); - $widget->setTitle(_('Varianten')); - $widget->addElement(new WidgetElement( - $template_factory->render('shared/modul_variants', - [ - 'variants' => $variants, - 'link' => $this->modulURL() - ]) - )); + $widget = new TemplateWidget( + _('Varianten'), + $this->get_template_factory()->open('shared/modul_variants'), + [ + 'variants' => $variants, + 'link' => $this->modulURL(), + ] + ); $sidebar->addWidget($widget, 'variants'); } } + $this->semester = array_reverse(Semester::getAll()); - $this->def_lang = $this->display_language === $this->modul->getDefaultLanguage(); - ModuleManagementModel::setContentLanguage($this->display_language); + $this->def_lang = $this->display_language === $this->modul->original_language; + I18NString::setDefaultLanguage($this->modul->original_language); + I18NString::setContentLanguage($this->display_language); if (!$this->def_lang) { $action_widget = $sidebar->getWidget('actions'); $action_widget->addLink( @@ -247,7 +264,6 @@ class Module_ModuleController extends MVVController ); } - $this->language = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['content_language']; if (Request::isPost()) { CSRFProtection::verifyUnsafeRequest(); $stored = false; @@ -279,6 +295,13 @@ class Module_ModuleController extends MVVController $this->modul->fassung_typ = Request::option('fassung_typ'); $this->modul->version = trim(Request::get('version')); $this->modul->verantwortlich = trim(Request::get('verantwortlich')); + // change original language + if ( + !$this->modul->isNew() + && $this->modul->original_language !== Request::option('original_language') + ) { + $this->setOriginalLanguage($this->modul, Request::option('original_language')); + } } $deskriptor_fields = ['bezeichnung', 'verantwortlich', @@ -290,10 +313,16 @@ class Module_ModuleController extends MVVController foreach ($deskriptor_fields as $deskriptor_field) { if ($this->deskriptor->isI18nField($deskriptor_field)) { - $this->deskriptor->$deskriptor_field->setLocalized( - trim(Request::get($deskriptor_field)), - $this->language - ); + if ($this->display_language === $this->modul->original_language) { + $this->deskriptor->$deskriptor_field->setOriginal( + trim(Request::get($deskriptor_field)) + ); + } else { + $this->deskriptor->$deskriptor_field->setLocalized( + trim(Request::get($deskriptor_field)), + $this->display_language + ); + } } else { $this->deskriptor->setValue( $deskriptor_field, @@ -307,7 +336,7 @@ class Module_ModuleController extends MVVController $df = $this->deskriptor->datafields->findOneBy('datafield_id', $df_key); if ($df) { $tdf = $df->getTypedDatafield(); - $tdf->setContentLanguage($this->language); + $tdf->setContentLanguage($this->display_language); $tdf->setValueFromSubmit($df_value); $tdf->store(); } @@ -652,54 +681,56 @@ class Module_ModuleController extends MVVController if ($this->modulteil->isNew()) { PageLayout::setTitle(_('Neuen Modulteil anlegen')); $success_message = ('Der Modulteil "%s" wurde angelegt.'); - $this->display_language = $this->modulteil->getDefaultLanguage(); - $this->deskriptor = $this->modulteil->getDeskriptor($this->display_language, true); + $this->display_language = Request::option( + 'display_language', + $this->modul->original_language + ); + $this->deskriptor = $this->modulteil->getDeskriptor(); PageLayout::postInfo(sprintf( - _('Sie legen einen neuen Modulteil für das Modul <em>%s</em> an. Der Modulteil muss zunächst in der Ausgabesprache <em>%s</em> angelegt werden.'), + _('Sie legen einen neuen Modulteil für das Modul <em>%1$s</em> an. Der Modulteil muss zunächst in der Ausgabesprache <em>%2$s</em> angelegt werden.'), htmlReady($this->modul->getDisplayName()), - htmlReady($GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['name']) + htmlReady($GLOBALS['CONTENT_LANGUAGES'][$this->display_language]['name']) )); // set default language of instruction - if ($GLOBALS['MVV_MODULTEIL']['SPRACHE']['default']) { + if (!empty($GLOBALS['MVV_MODULTEIL']['SPRACHE']['default'])) { $this->modulteil->assignLanguagesOfInstruction([ $GLOBALS['MVV_MODULTEIL']['SPRACHE']['default'] ]); } } else { - $this->display_language = Request::option('display_language', $this->modulteil->getDefaultLanguage()); - $this->deskriptor = $this->modulteil->getDeskriptor($this->display_language, true); - $this->translations = $this->deskriptor->getAvailableTranslations(); - + $this->display_language = Request::option('display_language', $this->modul->original_language); + $this->deskriptor = $this->modulteil->getDeskriptor(); + $this->translations = $this->deskriptor->getAvailableTranslations($this->modul->original_language); if (!in_array($this->display_language, $this->translations)) { PageLayout::setTitle(sprintf( - _('Modulteil: "%s" in der Ausgabesprache "%s" neu anlegen.'), + _('Modulteil: <em>%1$s</em> in der Ausgabesprache <em>%2$s</em> neu anlegen.'), $this->modulteil->getDisplayName(), - $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['name'] + $GLOBALS['CONTENT_LANGUAGES'][$this->display_language]['name'] )); } else { PageLayout::setTitle(sprintf(_('Modulteil: %s'), htmlReady($this->modulteil->getDisplayName()))); } - $success_message = _('Der Modulteil "%s" wurde geändert.'); - // sidebar widget for selecting language - $template_factory = $this->get_template_factory(); + $success_message = _('Der Modulteil <em>%s</em> wurde geändert.'); + $sidebar = Sidebar::get(); - $widget = new ListWidget(); - $widget->setTitle(_('Ausgabesprache')); - $widget_element = new WidgetElement( - $template_factory->render('shared/deskriptor_language', - [ - 'modul' => $this->modulteil, - 'sprache' => $this->display_language, - 'link' => $this->modulteilURL($this->modulteil->id), - 'url' => $this->url - ] - ) - ); - $widget->addElement($widget_element); - $sidebar->addWidget($widget, 'languages'); + $views_widget = new ViewsWidget(); + $views_widget->setTitle(_('Ausgabesprache')); + $content_languages = array_merge(array_flip($this->translations), $GLOBALS['CONTENT_LANGUAGES']); + foreach ($content_languages as $code => $language) { + $views_widget->addLink($language['name'] + . ' (' . ($code === $this->modul->original_language ? _('Originalfassung') . ', ' : '') + . (in_array($code, $this->translations) ? _('bearbeiten') : _('neu anlegen')) . ')', + URLHelper::getLink($this->modulteilURL($this->modulteil->id), + ['display_language' => $code] + ) + )->setActive($code === $this->display_language); + } + $sidebar->insertWidget($views_widget, 'actions','language'); } - $this->def_lang = $this->display_language === $this->modulteil->getDefaultLanguage(); + $this->def_lang = $this->display_language === $this->modul->original_language; + I18NString::setDefaultLanguage($this->modul->original_language); + I18NString::setContentLanguage($this->display_language); if (!$this->def_lang) { $action_widget = $sidebar->getWidget('actions'); @@ -711,7 +742,6 @@ class Module_ModuleController extends MVVController ); } - $this->language = $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['content_language']; if (Request::submitted('store')) { CSRFProtection::verifyUnsafeRequest(); $stored = false; @@ -748,12 +778,21 @@ class Module_ModuleController extends MVVController foreach ($deskriptor_fields as $deskriptor_field) { if ($this->deskriptor->isI18nField($deskriptor_field)) { - $this->deskriptor->$deskriptor_field->setLocalized( - trim(Request::get($deskriptor_field)), - $this->language - ); + if ($this->display_language === $this->modul->original_language) { + $this->deskriptor->$deskriptor_field->setOriginal( + trim(Request::get($deskriptor_field)) + ); + } else { + $this->deskriptor->$deskriptor_field->setLocalized( + trim(Request::get($deskriptor_field)), + $this->display_language + ); + } } else { - $this->deskriptor->setValue($deskriptor_field, trim(Request::get($deskriptor_field))); + $this->deskriptor->setValue( + $deskriptor_field, + trim(Request::get($deskriptor_field)) + ); } } @@ -762,7 +801,7 @@ class Module_ModuleController extends MVVController $df = $this->deskriptor->datafields->findOneBy('datafield_id', $df_key); if ($df) { $tdf = $df->getTypedDatafield(); - $tdf->setContentLanguage($this->language); + $tdf->setContentLanguage($this->display_language); $tdf->setValueFromSubmit($df_value); $tdf->store(); } @@ -795,23 +834,25 @@ class Module_ModuleController extends MVVController return; } } - if ($this->display_language !== $this->modulteil->getDefaultLanguage() && $this->deskriptor->isNew()) { + if ($this->display_language !== $this->modul->original_language && $this->deskriptor->isNew()) { PageLayout::postInfo(sprintf( _('Neue Beschreibung zum Modulteil "%s" in der Ausgabesprache %s anlegen.'), htmlReady($this->modulteil->getDisplayName()), - htmlReady($GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$this->display_language]['name']) + htmlReady($GLOBALS['CONTENT_LANGUAGES'][$this->display_language]['name']) )); } $this->cancel_url = $this->detailsURL($this->modulteil->modul_id); - $action_widget = Sidebar::get()->getWidget('actions'); - $action_widget->addLink( - _('Log-Einträge dieses Modulteils'), - $this->url_for('shared/log_event/show/Modulteil/' . $this->modulteil->id, - ['object2_type' => 'ModulteilDeskriptor', 'object2_id' => $this->deskriptor->id] - ), - Icon::create('log') - )->asDialog(); + if (!$this->modulteil->isNew()) { + $action_widget = Sidebar::get()->getWidget('actions'); + $action_widget->addLink( + _('Log-Einträge dieses Modulteils'), + $this->url_for('shared/log_event/show/Modulteil/' . $this->modulteil->id, + ['object2_type' => 'ModulteilDeskriptor', 'object2_id' => $this->deskriptor->id] + ), + Icon::create('log') + )->asDialog(); + } $this->render_template('module/module/modulteil', $this->layout); } @@ -828,7 +869,7 @@ class Module_ModuleController extends MVVController if (is_null($deskriptor)) { throw new Trails\Exception(404, _('Unbekannter Deskriptor')); } - $def_lang = $deskriptor->modulteil->getDefaultLanguage(); + $def_lang = $deskriptor->modulteil->modul->original_language; if ($language === $def_lang) { throw new Trails\Exception(403, _('Ein Deskriptor in der Original-Sprache kann nicht gelöscht werden.')); } @@ -1159,6 +1200,135 @@ class Module_ModuleController extends MVVController } } + public function change_language_action(string $module_id): void + { + $module = Modul::find($module_id); + if (!$module) { + throw new UnexpectedValueException('Unknown module.'); + } + PageLayout::setTitle(_('Originalsprache ändern')); + $this->translations = $module->deskriptoren->getAvailableTranslations($module->original_language); + $this->content_languages = $GLOBALS['CONTENT_LANGUAGES']; + $this->original_language = $module->original_language; + $this->module_id = $module->id; + } + + public function store_language_action(string $module_id): void + { + $module = Modul::find($module_id); + if (!$module) { + throw new UnexpectedValueException('Unknown module.'); + } + CSRFProtection::verifyUnsafeRequest(); + $new_language = Request::option('new_language'); + if ($new_language !== $module->original_language) { + $descriptor = $module->deskriptoren; + if (Request::bool('swap_data')) { + self::swap_translation($descriptor, $new_language, $module->original_language); + $module->modulteile->each( + fn($component) => self::swap_translation( + $component->deskriptoren, + $new_language, + $module->original_language + ) + ); + } else { + self::swap_language($module->deskriptoren, $new_language, $module->original_language); + $module->modulteile->each( + fn($component) => self::swap_language( + $component->deskriptoren, + $new_language, + $module->original_language + ) + ); + } + $module->original_language = $new_language; + $module->store(); + } else { + throw new UnexpectedValueException('New language has to be different from current language.'); + } + $this->relocate('module/module/index'); + } + + /** + * Swaps the language of the descriptor, but not the translated content. + * + * @param ModulDeskriptor|ModulteilDeskriptor $descriptor The descriptor of a module or a module component. + * @param string $new_language The language to swap to as language code. + * @param string $old_language The current languageas language code. + * @return int|bool Number of swapped translations or false if no translation is available. + */ + private static function swap_language( + ModulDeskriptor|ModulteilDeskriptor $descriptor, + string $new_language, + string $old_language + ): int|bool + { + // change language setting in i18n for this descriptor if a translation exists + $translations = $descriptor->getAvailableTranslations($old_language); + if (count($translations) > 1) { + $metadata = $descriptor->getTableMetadata(); + foreach (array_keys($metadata['fields']) as $field) { + if ($descriptor->isI18nField($field)) { + $i18n_field = $descriptor->$field; + $i18n_field->setDefaultLanguage($old_language); + $translation = $i18n_field->translation($new_language); + if (!empty($translation)) { + $translations = $i18n_field->toArray(); + unset($translations[$new_language]); + $translations[$old_language] = $translation; + $i18n_field->setTranslations($translations); + } + $i18n_field->setDefaultLanguage($new_language); + } + } + return $descriptor->store(); + } + return false; + } + + /** + * Swaps the language of the descriptor, swaps the translated content also. + * + * @param ModulDeskriptor|ModulteilDeskriptor $descriptor The descriptor of a module or a module component. + * @param string $new_language The language to swap to as language code. + * @param string $old_language The current language as language code. + * @return int|bool Number of swapped translations or false if no translation is available. + */ + private static function swap_translation( + ModulDeskriptor|ModulteilDeskriptor $descriptor, + string $new_language, + string $old_language + ): int|bool + { + if ( + !array_key_exists($new_language, $GLOBALS['CONTENT_LANGUAGES']) + || !array_key_exists($old_language, $GLOBALS['CONTENT_LANGUAGES']) + ) { + throw new UnexpectedValueException('Language code refers to no content language.'); + } + $count = 0; + $meta_data = $descriptor->getTableMetadata(); + $descriptor_class = $descriptor::class; + foreach ($meta_data['fields'] as $field => $foo) { + if ($descriptor->isI18nField($field)) { + $i18n_field = $descriptor->$field; + $i18n_field->setDefaultLanguage($old_language); + $new_base_content = $i18n_field->translation($new_language); + $old_base_content = $i18n_field->original(); + $i18n_field->setDefaultLanguage($new_language); + if (!empty($new_base_content)) { + $i18n_field->setOriginal($new_base_content); + $i18n_field->setLocalized($old_base_content, $old_language); + } + $lang = $i18n_field->toArray(); + unset($lang[$new_language]); + $i18n_field->setTranslations($lang); + } + } + return $descriptor->store(); + } + /** * do the search */ @@ -1332,25 +1502,14 @@ class Module_ModuleController extends MVVController { $sidebar = Sidebar::get(); - $widget = new ViewsWidget(); - $widget->addLink( - _('Liste der Module'), - $this->url_for('module/module/index') - )->setActive(get_called_class() === 'Module_ModuleController'); - $widget->addLink( - _('Gruppiert nach verantwortlichen Einrichtungen'), - $this->url_for('module/institute/index') - )->setActive(get_called_class() === 'Module_InstituteController'); - $sidebar->addWidget($widget, 'views'); - $widget = new ActionsWidget(); $widget->setTitle(_('Aktionen')); if (MvvPerm::havePermCreate('Modul')) { $widget->addLink( _('Neues Modul anlegen'), - $this->modulURL(), + $this->select_module_languageURL(), Icon::create('add') - ); + )->asDialog('size=auto'); } $sidebar->addWidget($widget, 'actions'); @@ -1573,4 +1732,47 @@ class Module_ModuleController extends MVVController WHERE `mvv_studiengang`.`abschluss_id` = ?"; return DBManager::get()->fetchFirst($query, [$abschluss_id]); } + + /** + * Sets the original language for the given module. + * + * @param Modul $module Sets the original language for this module. + * @param string $original_language The original language as language code. + * @return void + */ + private function setOriginalLanguage(Modul $module, string $original_language): void + { + $content_language = $GLOBALS['CONTENT_LANGUAGES'][$original_language]; + if (empty($content_language)) { + throw new InvalidArgumentException("Original language $original_language is not defined"); + } + if ($module->deskriptoren) { + $current_language = $module->original_language; + $module->original_language = $original_language; + DBManager::get()->execute(" + UPDATE `i18n` + SET `lang` = ? + WHERE `object_id` = ? + AND `table` = 'mvv_modul_deskriptor' + AND `lang` = ?", + [ + $original_language, + $module->deskriptoren->id, + $current_language + ]); + $module->modulteile->each(fn($component) => DBManager::get()->execute(" + UPDATE `i18n` + SET `lang` = ? + WHERE `object_id` IN (?) + AND `table` = 'mvv_modulteil_deskriptor' + AND `lang` = ?", + [ + $original_language, + $component->deskriptoren->id, + $current_language + ] + ) + ); + } + } } diff --git a/app/controllers/search/angebot.php b/app/controllers/search/angebot.php index f2b532197257fab72278b00072b78f80a44c2032..0c0f402f86624ae5485a8e9545d535a7c9a90a27 100644 --- a/app/controllers/search/angebot.php +++ b/app/controllers/search/angebot.php @@ -172,7 +172,7 @@ class Search_AngebotController extends MVVController public function verlauf_action($stgteil_id, $stgteil_bez_id = null, $studiengang_id = null) { - ModuleManagementModel::setLanguage($_SESSION['_language']); + ModuleManagementModel::setContentLanguage($_SESSION['_language']); $response = $this->relay('search/studiengaenge/verlauf', $stgteil_id, $stgteil_bez_id, $studiengang_id); diff --git a/app/controllers/search/studiengaenge.php b/app/controllers/search/studiengaenge.php index 0dd5c7d9f1a7af22ab64ab27d2fcd4fa1a691d4c..8f08c329967ff7111208778dbfb853104fcbae83 100644 --- a/app/controllers/search/studiengaenge.php +++ b/app/controllers/search/studiengaenge.php @@ -341,15 +341,17 @@ class Search_StudiengaengeController extends MVVController // add links to export Modulhandbücher as PDF $widget = new ActionsWidget(); $widget->setTitle(_('Aktuelle Modulhandbücher')); - $avl_lang = array_keys($GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values']); - - foreach ($avl_lang as $language) { - if ($language === $GLOBALS['MVV_LANGUAGES']['default']) { + $content_languages = array_merge( + ['original' => ['name' => _('Originalfassung')]], + $GLOBALS['CONTENT_LANGUAGES'] + ); + foreach (array_keys($content_languages) as $language) { + if ($language === 'original') { $title = _('Originalfassung als PDF'); } else { $title = sprintf( - _('Zweitfassung (%s) als PDF'), - $GLOBALS['MVV_LANGUAGES']['values'][$language]['name'] + _('Ausgabesprache (%s) als PDF'), + $content_languages[$language]['name'] ); } // get link without registered parameters @@ -373,7 +375,7 @@ class Search_StudiengaengeController extends MVVController public function info_action($studiengang_id, $language = null) { $language = $language ?: Request::get('language', $_SESSION['_language']); - ModuleManagementModel::setLanguage($language); + ModuleManagementModel::setContentLanguage($language); $this->studiengang = Studiengang::find($studiengang_id); if (!$this->studiengang) { @@ -391,23 +393,23 @@ class Search_StudiengaengeController extends MVVController $file = $document->mvv_file; if ($file->extern_visible) { $mvv_file_ref = null; - foreach ($GLOBALS['MVV_LANGUAGES']['values'] as $key => $mvv_language) { - if ($mvv_language['locale'] === $_SESSION['_language']) { - $mvv_file_ref = $file->file_refs->findOneBy('file_language', $key); + foreach ($GLOBALS['CONTENT_LANGUAGES'] as $language_key => $mvv_language) { + if ($language_key === $_SESSION['_language']) { + $mvv_file_ref = $file->file_refs->findOneBy('file_language', $language_key); } else { - $mvv_file_ref = $file->file_refs->findOneBy('file_language', $GLOBALS['MVV_LANGUAGES']['default']); + $mvv_file_ref = $file->file_refs->findOneBy('file_language', Config::get()->MVV_DEFAULT_LANGUAGE); } } if ($mvv_file_ref) { $filetype = $mvv_file_ref->file_ref->getFileType(); $this->all_documents[$file->category][$file->id] = - [ - 'name' => $file->getDisplayName(), - 'url' => $mvv_file_ref->file_ref->getDownloadURL(), - 'metadata_url' => $mvv_file_ref->file_ref->file->metadata['url'] ?? null, - 'extension' => $mvv_file_ref->file_ref->file->getExtension(), - 'is_link' => ($filetype instanceof URLFile) - ]; + [ + 'name' => $file->getDisplayName(), + 'url' => $mvv_file_ref->file_ref->getDownloadURL(), + 'metadata_url' => $mvv_file_ref->file_ref->file->metadata['url'] ?? null, + 'extension' => $mvv_file_ref->file_ref->file->getExtension(), + 'is_link' => ($filetype instanceof URLFile) + ]; } } } diff --git a/app/controllers/seminar/details.php b/app/controllers/seminar/details.php index 3ce2fab122b681e1d45377f4b65a19b43118927b..6750fa63cb7c242a055b1d706d08dc046fbc134b 100644 --- a/app/controllers/seminar/details.php +++ b/app/controllers/seminar/details.php @@ -21,7 +21,7 @@ class Seminar_DetailsController extends MVVController public function before_filter(&$action, &$args) { parent::before_filter($action, $args); - ModuleManagementModel::setLanguage($_SESSION['_language']); + ModuleManagementModel::setContentLanguage($_SESSION['_language']); if (Request::isXhr()) { $this->set_layout(null); @@ -38,4 +38,4 @@ class Seminar_DetailsController extends MVVController $this->mvv_pathes = MvvCourse::get($seminar_id)->getTrails($trail_classes); } -} \ No newline at end of file +} diff --git a/app/controllers/shared/download.php b/app/controllers/shared/download.php index f94bc86f10001e11f1f109b92ca8d20178d7686f..6e3999823ece00a582c12c2f8617b8c839054aa3 100644 --- a/app/controllers/shared/download.php +++ b/app/controllers/shared/download.php @@ -154,7 +154,7 @@ class Shared_DownloadController extends AuthenticatedController public function getMVVPluginModulDescription($modul, $display_language = null) { if ($display_language == null) { - $display_language = $GLOBALS['MVV_LANGUAGES']['default']; + $display_language = Config::get()->MVV_DEFAULT_LANGUAGE; } $path = $GLOBALS['STUDIP_BASE_PATH'] . '/app/views/shared/modul/'; @@ -168,8 +168,7 @@ class Shared_DownloadController extends AuthenticatedController $factory = new Flexi\Factory($path); $type = 1; - if (count($modul->modulteile) == 1) { - $modulteil = $modul->modulteile->first(); + if (count($modul->modulteile) === 1) { $type = 2; } elseif (count($modul->modulteile) === 0) { $type = 3; diff --git a/app/controllers/shared/modul.php b/app/controllers/shared/modul.php index d1a6ecfb21625f335418b20d88121703ebb5b37a..2cb9a8555115c1d6f35fe7a23712a2245cbc1914 100644 --- a/app/controllers/shared/modul.php +++ b/app/controllers/shared/modul.php @@ -13,8 +13,6 @@ * @since 3.5 */ - - class Shared_ModulController extends AuthenticatedController { @@ -28,98 +26,91 @@ class Shared_ModulController extends AuthenticatedController public function overview_action($modul_id, $semester_id = null) { $display_language = Request::option('display_language', $_SESSION['_language']); - ModuleManagementModel::setLanguage($display_language); + ModuleManagementModel::setContentLanguage($display_language); - $modul = Modul::find($modul_id); - if (!$modul->hasPublicStatus()) { + $this->modul = Modul::find($modul_id); + if (!$this->modul->hasPublicStatus()) { throw new AccessDeniedException(); } - if ($modul) { - $this->details_id = $modul->getId(); + if ($this->modul) { + $this->details_id = $this->modul->getId(); $type = 1; - if (count($modul->modulteile) == 1) { - $modulteil = $modul->modulteile->first(); + if (count($this->modul->modulteile) == 1) { + $modulteil = $this->modul->modulteile->first(); $type = 3; if (count($modulteil->lvgruppen) > 0) { $type = 2; } - } else if (count($modul->modulteile) == 0) { + } else if (count($this->modul->modulteile) == 0) { $type = 3; } if (!$semester_id) { - $currentSemester = Semester::findDefault(); + $current_semester = Semester::findDefault(); } else { - $currentSemester = Semester::find($semester_id); + $current_semester = Semester::find($semester_id); } $sws = 0; - $institut = new Institute($modul->responsible_institute->institut_id); - $modulTeileData = []; - foreach ($modul->modulteile as $modulTeil) { - - $modulTeilDeskriptor = $modulTeil->getDeskriptor($display_language); - - $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); - - $modulTeileData[$modulTeil->getId()] = [ - 'name' => $modulTeil->getDisplayName(), + $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' => $modulTeilDeskriptor->voraussetzung, - 'pruef_leistung' => $modulTeilDeskriptor->pruef_leistung, - 'pruef_vorleistung' => $modulTeilDeskriptor->pruef_vorleistung, - 'kommentar' => $modulTeilDeskriptor->kommentar, - 'kapazitaet' => $modulTeil->kapazitaet, + '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()); + $lvGruppen = Lvgruppe::findByModulteil($modulteil->getId()); foreach ($lvGruppen as $lvGruppe) { - $ids = array_column($lvGruppe->getAssignedCoursesBySemester($currentSemester['semester_id'], $GLOBALS['user']->id), 'seminar_id'); + $ids = array_column($lvGruppe->getAssignedCoursesBySemester($current_semester['semester_id'], $GLOBALS['user']->id), 'seminar_id'); $courses = Course::findMany($ids, 'order by Veranstaltungsnummer, Name'); - $modulTeileData[$modulTeil->getId()]['lvGruppen'][$lvGruppe->getId()] = [ + $modulteile_data[$modulteil->getId()]['lvGruppen'][$lvGruppe->getId()] = [ 'courses' => $courses, 'alt_texte' => $lvGruppe->alttext ]; } } - $this->modulTeile = $modulTeileData; - $this->deskriptor = $modul->getDeskriptor($display_language); + $this->modulteile = $modulteile_data; + $this->deskriptor = $this->modul->getDeskriptor(); $this->institut = $institut; - $this->semester = $currentSemester; + $this->semester = $current_semester; $this->sws = $sws; - $this->pruef_ebene = $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->pruef_ebene]['name'] ?? null; - $this->modul = $modul; + $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); - $this->teilnahmeVoraussetzung = $modul->getDeskriptor()->voraussetzung; - PageLayout::setTitle($modul->getDisplayName() . ' (' . _('Veranstaltungsübersicht') .')'); + PageLayout::setTitle($this->modul->getDisplayName() . ' (' . _('Veranstaltungsübersicht') .')'); } } public function description_action($id) { - $modul = Modul::find($id); - $perm = MvvPerm::get($modul); - if (!($modul->hasPublicStatus() || $perm->haveObjectPerm(MvvPerm::PERM_READ))) { + $this->modul = Modul::find($id); + $perm = MvvPerm::get($this->modul); + if (!($this->modul->hasPublicStatus() || $perm->haveObjectPerm(MvvPerm::PERM_READ))) { throw new AccessDeniedException(); } - $type = 1; - if (count($modul->modulteile) == 1) { - $modulteil = $modul->modulteile->first(); - $type = 3; + $this->type = 1; + if (count($this->modul->modulteile) == 1) { + $modulteil = $this->modul->modulteile->first(); + $this->type = 3; if (count($modulteil->lvgruppen) > 0) { - $type = 2; + $this->type = 2; } - } else if (count($modul->modulteile) == 0) { - $type = 3; + } else if (count($this->modul->modulteile) == 0) { + $this->type = 3; } if (!Request::get('sem_select')) { @@ -128,28 +119,27 @@ class Shared_ModulController extends AuthenticatedController $currentSemester = Semester::find(Request::get('sem_select')); } - $display_language = Request::get('display_language', $_SESSION['_language']); - ModuleManagementModel::setLanguage($display_language); + $this->display_language = Request::get('display_language', $this->modul->original_language); + ModuleManagementModel::setContentLanguage($this->display_language); + I18NString::setDefaultLanguage($this->modul->original_language); + I18NString::setContentLanguage($this->display_language); $this->semesterSelector = Semester::getSemesterSelector(null, $currentSemester['semester_id'], 'semester_id', false); - $this->modul = $modul; - $this->pruefungsEbene = isset($GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->pruef_ebene]) - ? $GLOBALS['MVV_MODUL']['PRUEF_EBENE']['values'][$modul->pruef_ebene]['name'] + $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 = $modul->getDeskriptor($display_language); - $this->startSemester = Semester::findByTimestamp($modul->start); + $this->modulDeskriptor = $this->modul->getDeskriptor(); + $this->startSemester = Semester::findByTimestamp($this->modul->start); - if (!$modul->responsible_institute) { + if (!$this->modul->responsible_institute) { $this->instituteName = null; - } elseif ($modul->responsible_institute->institute) { - $this->instituteName = $modul->responsible_institute->institute->name; + } elseif ($this->modul->responsible_institute->institute) { + $this->instituteName = $this->modul->responsible_institute->institute->name; } else { $this->instituteName = _('Unbekannte Einrichtung'); } - $this->type = $type; $this->semester = $currentSemester; - $this->display_language = $display_language; - PageLayout::setTitle($modul->getDisplayName() . ' (' . _('Vollständige Modulbeschreibung') .')'); + PageLayout::setTitle($this->modul->getDisplayName() . ' (' . _('Vollständige Modulbeschreibung') .')'); } public function mail_action($modul_id, $semester_id) diff --git a/app/controllers/studiengaenge/studiengaenge.php b/app/controllers/studiengaenge/studiengaenge.php index 44f5d83d654b377312551000f4cb57dd24ee40a5..809d1ab35906c6ab79e0091bbcd6d63a2e94f2cf 100644 --- a/app/controllers/studiengaenge/studiengaenge.php +++ b/app/controllers/studiengaenge/studiengaenge.php @@ -1215,11 +1215,11 @@ class Studiengaenge_StudiengaengeController extends MVVController $file = $document->mvv_file; if ($file->extern_visible) { $mvv_file_ref = null; - foreach ($GLOBALS['MVV_LANGUAGES']['values'] as $key => $mvv_language) { - if ($mvv_language['locale'] === $_SESSION['_language']) { - $mvv_file_ref = $file->file_refs->findOneBy('file_language', $key); + foreach ($GLOBALS['CONTENT_LANGUAGES'] as $code => $content_language) { + if ($code === $_SESSION['_language']) { + $mvv_file_ref = $file->file_refs->findOneBy('file_language', $code); } else { - $mvv_file_ref = $file->file_refs->findOneBy('file_language', $GLOBALS['MVV_LANGUAGES']['default']); + $mvv_file_ref = $file->file_refs->findOneBy('file_language', Config::get()->MVV_DEFAULT_LANGUAGE); } } if ($mvv_file_ref) { diff --git a/app/views/admin/datafields/edit.php b/app/views/admin/datafields/edit.php index 46b7aa1dcb8c988220d3a291f4ff4aabea6fe753..c3f67b4d2fb66c6be93b0794af3d64c2d754b334 100644 --- a/app/views/admin/datafields/edit.php +++ b/app/views/admin/datafields/edit.php @@ -71,7 +71,7 @@ use Studip\Button, Studip\LinkButton; <select multiple name="object_class[]" id="object_class" required> <option value="NULL" <? if ($item->object_class === null) echo 'selected'; ?>><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option> - <? foreach ((array) $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?> + <? foreach ($GLOBALS['CONTENT_LANGUAGES'] as $key => $value) : ?> <option value="<?= htmlReady($key) ?>" <? if (mb_strpos($item->object_class, $key) !== false) echo 'selected'; ?>> <?= htmlReady($value['name']) ?> </option> @@ -82,7 +82,7 @@ use Studip\Button, Studip\LinkButton; <select multiple name="object_class[]" id="object_class" required> <option value="NULL" <? if ($item->object_class === null) echo 'selected'; ?>><?= _('alle (mehrsprachige Eingabe)') ?></option> - <? foreach ((array) $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?> + <? foreach ($GLOBALS['CONTENT_LANGUAGES'] as $key => $value) : ?> <option value="<?= htmlReady($key) ?>" <? if (mb_strpos($item->object_class, $key) !== false) echo 'selected'; ?>> <?= htmlReady($value['name']) ?> </option> @@ -90,7 +90,7 @@ use Studip\Button, Studip\LinkButton; </select> <? elseif ($item->object_type === 'studycourse'): ?> <?= _('Typ/Abschnitt') ?> - + <select name="object_class" required> <option value="all_settings"<?= mb_strpos($item->object_class, 'all_settings') !== false ? ' selected' : '' ?>><?= _('alle (Abschnitt "Einstellungen")') ?></option> <option value="all_info"<?= mb_strpos($item->object_class, 'all_info') !== false ? ' selected' : '' ?>><?= _('alle (Abschnitt "Inhalte und Informationen")') ?></option> diff --git a/app/views/admin/datafields/index.php b/app/views/admin/datafields/index.php index e62b8d6fd0004832747a165d16ad94fd22a1694b..81ac85fcd5983191410cd96763627bd30b3c1c59 100644 --- a/app/views/admin/datafields/index.php +++ b/app/views/admin/datafields/index.php @@ -108,7 +108,7 @@ <?= $val->object_class !== null ? htmlReady($GLOBALS['INST_TYPE'][$val->object_class]['name']) : _('alle')?> <? elseif ($key === 'moduldeskriptor' || $key === 'modulteildeskriptor') : ?> <?= $val->object_class !== null ? htmlReady(implode(', ', array_map(function ($class) { - return $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'][$class]['name']; + return $GLOBALS['CONTENT_LANGUAGES'][$class]['name']; }, explode(',', $val->object_class)))) : _('alle')?> <? elseif ($key === 'studycourse'): ?> <? $object_classes = diff --git a/app/views/admin/datafields/new.php b/app/views/admin/datafields/new.php index e64293ff5b6f354b2abcc88072924ea1d0917a06..c749ff9cd4cc212b6fcbf4d178278b1952429d57 100644 --- a/app/views/admin/datafields/new.php +++ b/app/views/admin/datafields/new.php @@ -72,13 +72,13 @@ use Studip\Button, Studip\LinkButton; <? elseif ($object_typ === 'moduldeskriptor') : ?> <select multiple name="object_class[]" required> <option value="NULL" selected><?= _('alle (mehrsprachige Eingabe bei Feldtyp textline, textarea, textmarkup)') ?></option> - <? foreach ((array) $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?> + <? 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 ((array) $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'] as $key => $value) : ?> + <? foreach ($GLOBALS['CONTENT_LANGUAGES'] as $key => $value) : ?> <option value="<?= htmlReady($key) ?>"><?= htmlReady($value['name']) ?></option> <? endforeach; ?> <? elseif ($object_typ === 'studycourse') : ?> diff --git a/app/views/materialien/files/add_dokument.php b/app/views/materialien/files/add_dokument.php index 0782f088b63f99237932859edde34768f4c72220..bc72ce2446d917991c81f4c84e773fbef6ba2160 100644 --- a/app/views/materialien/files/add_dokument.php +++ b/app/views/materialien/files/add_dokument.php @@ -21,33 +21,33 @@ </label> <table class="default mvv-files-table"> - <? foreach($GLOBALS['MVV_LANGUAGES']['values'] as $key => $entry) : ?> + <? foreach($GLOBALS['CONTENT_LANGUAGES'] as $language_key => $entry) : ?> <tr> <td rowspan="2"> - <?= Assets::img(MVV::getContentLanguageImagePath($key), ['alt' => $entry['name'], 'size' => 24]) ?> + <?= Assets::img(MVV::getContentLanguageImagePath($language_key), ['alt' => $entry['name'], 'size' => 24]) ?> </td> <td> <label> <?= _('Angezeigter Name des Dokuments') ?> - <input name="doc_displayname_<?= $key; ?>" type="text" value="<?= !isset($documents[$key]) ? '' : htmlReady($documents[$key]->name) ?>"<?= $perm->disable('name') ?>> + <input name="doc_displayname_<?= $language_key; ?>" type="text" value="<?= !isset($documents[$language_key]) ? '' : htmlReady($documents[$language_key]->name) ?>"<?= $perm->disable('name') ?>> </label> </td> </tr> <tr> <td> <div class="attachments" style="<?= (empty($documents) || !array_key_exists($key, $documents)) ? '' : 'display: none;'?>"> - <span style="cursor:pointer;" onClick="$('#fileselector_<?= $key; ?>').toggle();$(this).toggle();"> - <?= Icon::create('add', Icon::ROLE_CLICKABLE, ['title' => _("Datei hinzufügen"), 'class' => 'text-bottom']); ?> - <?= _("Datei hinzufügen") ?> + <span style="cursor:pointer;" onClick="$('#fileselector_<?= $language_key; ?>').toggle();$(this).toggle();"> + <?= Icon::create('add')->asImg(['title' => _('Datei hinzufügen'), 'class' => 'text-bottom']); ?> + <?= _('Datei hinzufügen') ?> </span> - <div id="fileselector_<?= $key; ?>" style="display:none;"> + <div id="fileselector_<?= $language_key; ?>" style="display:none;"> <ul class="stgfiles list-unstyled"> <li style="display: none;" class="stgfile"> <input type="hidden" name="document_id" id="document_id" value="<?= htmlReady($document_id ?? '') ?>"> <span class="icon"></span> <span class="name"></span> <span class="size"></span> - <button class="refresh_attachment as-link" data-language="<?= htmlReady($key) ?>"> + <button class="refresh_attachment as-link" data-language="<?= htmlReady($language_key) ?>"> <?= Icon::create('refresh')->asImg([ 'class' => 'text-bottom', 'title' => _('Datei aktualisieren'), @@ -68,29 +68,29 @@ </div> </div> <label id="upload_chooser" style="cursor: pointer;"> - <input type="file" id="fileupload" multiple onChange="STUDIP.MVV.Document.upload_from_input(this, '<?= $key; ?>');" style="display: none;"> - <?= Icon::create('upload', 'clickable', ['title' => _("Datei hochladen"), 'class' => "text-bottom"]) ?> + <input type="file" id="fileupload" multiple onChange="STUDIP.MVV.Document.upload_from_input(this, '<?= $language_key; ?>');" style="display: none;"> + <?= Icon::create('upload')->asImg(['title' => _('Datei hochladen'), 'class' => 'text-bottom']) ?> <?= _("Datei hochladen") ?> </label> <br> <b><?= _('oder'); ?></b> <label> <?= _('Link hinzufügen') ?> - <input name="doc_url_<?= $key; ?>" type="text" value="" placeholder="https://..."> + <input name="doc_url_<?= $language_key; ?>" type="text" value="" placeholder="https://..."> </label> <div id="upload_finished" style="display: none"><?= _("wird verarbeitet") ?></div> <div id="upload_received_data" style="display: none"><?= _("gespeichert") ?></div> </div> </div> - <div id="fileviewer_<?= $key; ?>"> + <div id="fileviewer_<?= $language_key; ?>"> <ul class="stgfiles list-unstyled"> - <? if (isset($documents[$key])): ?> + <? if (isset($documents[$language_key])): ?> <li class="stgfile"> - <input type="hidden" name="document_id" id="document_id" value="<?= htmlReady($documents[$key]->fileref_id) ?>"> + <input type="hidden" name="document_id" id="document_id" value="<?= htmlReady($documents[$language_key]->fileref_id) ?>"> <span class="icon"><?= Icon::create('file', Icon::ROLE_INFO, ['class' => 'text-bottom']); ?></span> - <span class="name"><?= htmlReady($documents[$key]->filename) ?></span> - <span class="size"><?= relsize($documents[$key]->file_ref->size) ?></span> - <button class="refresh_attachment as-link" data-language="<?= htmlReady($key) ?>"> + <span class="name"><?= htmlReady($documents[$language_key]->filename) ?></span> + <span class="size"><?= relsize($documents[$language_key]->file_ref->size) ?></span> + <button class="refresh_attachment as-link" data-language="<?= htmlReady($language_key) ?>"> <?= Icon::create('refresh')->asImg([ 'class' => 'text-bottom', 'title' => _('Datei aktualisieren'), diff --git a/app/views/module/institute/details.php b/app/views/module/institute/details.php index c62b4bbab5cbb7ef03be61d52c6fd9ab6f1a4b1e..d50953d00bacd64a89adc7873f19c79c2e562bd8 100644 --- a/app/views/module/institute/details.php +++ b/app/views/module/institute/details.php @@ -6,7 +6,7 @@ <th><?= _('Modul') ?></th> <th style="width: 5%;"><?= _('Fassung') ?></th> <th style="width: 5%;"><?= _('Modulteile') ?></th> - <th style="text-align: center; width: 150px;"> + <th style="width: 150px;"> <?= _('Ausgabesprachen') ?> </th> <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th> @@ -14,4 +14,4 @@ </thead> <?= $this->render_partial('module/module/module') ?> </table> -</td> \ No newline at end of file +</td> diff --git a/app/views/module/module/change_language.php b/app/views/module/module/change_language.php new file mode 100644 index 0000000000000000000000000000000000000000..178b93b6dc71a428b1b360f02baa6bd5c51d4ccf --- /dev/null +++ b/app/views/module/module/change_language.php @@ -0,0 +1,36 @@ +<?php +/** + * @var Module_ModuleController $controller + * @var array $content_languages + * @var string $original_language + * @var string $module_id + * @var array $translations + */ +?> +<form class="default" action="<?= $controller->store_language($module_id) ?>" method="post"> + <?= CSRFProtection::tokenTag() ?> + <fieldset> + <legend> + <?= _('Wählen Sie die neue Sprache der Originalfassung') ?> + </legend> + <label> + <?= _('Neue Originalsprache') ?> + <select name="new_language"> + <? foreach ($content_languages as $code => $language) : ?> + <? if ($code !== $original_language) : ?> + <option value="<?= htmlReady($code) ?>"><?= htmlReady($language['name']) ?></option> + <? endif ?> + <? endforeach ?> + </select> + </label> + <? if (count($translations) > 1) : ?> + <label> + <input type="checkbox" name="swap_data" value="1"> + <?= _('Inhalte tauschen') ?> + </label> + <? endif ?> + </fieldset> + <footer data-dialog-button> + <?= Studip\Button::createAccept(_('Sprache ändern'))?> + </footer> +</form> diff --git a/app/views/module/module/details.php b/app/views/module/module/details.php index 4509d520e345caab979aa8f98a7132cdbe5aa99b..257d181b2553e1ef951ad198779733b636492c25 100644 --- a/app/views/module/module/details.php +++ b/app/views/module/module/details.php @@ -1,8 +1,19 @@ +<?php +/** + * @var Modul $modul + * @var string $modulteil_id + * @var string $display_language + * @var Module_ModuleController $controller + * @var string $institut_id + */ +?> + <td colspan="6"> <table class="default collapsable sortable" id="<?= $modul->id ?>"> <colgroup> <col> - <col span="2" style="width: 150px;"> + <col style="width: 150px;"> + <col style="width: 70px;"> </colgroup> <? foreach ($modul->modulteile as $modulteil) : ?> <? $perm = MvvPerm::get($modulteil) ?> @@ -18,10 +29,10 @@ <?= htmlReady($modulteil->getDisplayName()) ?> <? endif; ?> </td> - <td class="dont-hide actions" style="white-space: nowrap; text-align: center;"> + <td class="dont-hide actions" style="white-space: nowrap; text-align: left;"> <? if ($perm->havePermWrite()) : ?> - <? foreach ($modulteil->deskriptoren->getAvailableTranslations() as $language) : ?> - <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?> + <? foreach ($modulteil->deskriptoren->getAvailableTranslations($modulteil->modul->original_language) as $language) : ?> + <? $lang = $GLOBALS['CONTENT_LANGUAGES'][$language]; ?> <a href="<?= $controller->action_link('modulteil/' . join('/', [$modulteil->id, $institut_id]), ['display_language' => $language]) ?>"> <?= Assets::img(MVV::getContentLanguageImagePath($language), ['alt' => $lang['name'], 'size' => 24]) ?> </a> diff --git a/app/views/module/module/index.php b/app/views/module/module/index.php index 1028a2db12067eaa8d27859ab4b35ea56605702a..37088d57acb32470249a78e8ac34daddaeb39b84 100644 --- a/app/views/module/module/index.php +++ b/app/views/module/module/index.php @@ -1,5 +1,21 @@ +<?php +/** + * @var Module_ModuleController $controller + * @var int $count + * @var int $page + */ +?> + <?= $controller->jsUrl() ?> <table class="default collapsable"> + <colgroup> + <col> + <col> + <col> + <col> + <col style="width: 150px"> + <col style="width: 70px"> + </colgroup> <caption> <?= _('Module')?> <span class="actions"><?= sprintf(ngettext('%s Modul', '%s Module', $count), $count) ?></span> @@ -10,10 +26,10 @@ <?= $controller->renderSortLink('module/module/', _('Modul'), 'bezeichnung') ?> <?= $controller->renderSortLink('module/module/', _('Fassung'), 'fassung_nr', ['style' => 'width: 5%;']) ?> <?= $controller->renderSortLink('module/module/', _('Modulteile'), 'count_modulteile', ['style' => 'width: 5%;']) ?> - <th style="text-align: right; width: 150px;"> + <th> <?= _('Ausgabesprachen') ?> </th> - <th style="width: 5%; text-align: right;"><?= _('Aktionen') ?></th> + <th style="text-align: right;"><?= _('Aktionen') ?></th> </tr> </thead> <?= $this->render_partial('module/module/module') ?> diff --git a/app/views/module/module/modul.php b/app/views/module/module/modul.php index e209a1808b4bee1afe338827260c23784e762ffb..1a8971fb175913de8ba57332a4127916d3c6e82b 100644 --- a/app/views/module/module/modul.php +++ b/app/views/module/module/modul.php @@ -1,9 +1,29 @@ +<?php +/** + * @var Module_ModuleController $controller + * @var Modul $modul + * @var ModulDeskriptor $deskriptor + * @var string $display_language + * @var boolean $def_lang + * @var QuickSearch $search_modul + * @var string $qs_id_module + * @var Semester[] $semester + * @var QuickSearch $search_responsible + * @var string $qs_id_responsible + * @var QuickSearch $search_institutes + * @var string $qs_id_institutes + * @var SimpleORMapCollection $contacts + * @var array $translations + * @var string $cancel_url + */ +?> + <? use Studip\Button, Studip\LinkButton; ?> <?= $controller->jsUrl() ?> <? $perm = MvvPerm::get($modul); $perm_d = MvvPerm::get($deskriptor); -if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { +if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] !== $display_language) { $perm_d->setVariant($display_language); } ?> @@ -144,12 +164,12 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { <?= _('Beschlussdatum:') ?> <? if ($perm->haveFieldPerm('beschlussdatum')) : ?> <input type="text" name="beschlussdatum" - value="<?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?>" + value="<?= $modul->beschlussdatum ? date('d.m.Y', $modul->beschlussdatum) : '' ?>" placeholder="<?= _('TT.MM.JJJJ') ?>" class="with-datepicker"> <? else : ?> - <?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?> + <?= $modul->beschlussdatum ? date('d.m.Y', $modul->beschlussdatum) : '' ?> <input type="hidden" name="beschlussdatum" - value="<?= ($modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : '') ?>"> + value="<?= $modul->beschlussdatum ? date('d.m.Y', $modul->beschlussdatum) : '' ?>"> <? endif; ?> </label> <label for="mvv-field-modul-fassung_nr"><?= _('Fassung:') ?> @@ -196,7 +216,7 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { </div> <div id="mvv-field-modul-beschlussdatum"> <? printf(_('Beschlussdatum: %s'), - $modul->beschlussdatum ? strftime('%d.%m.%Y', $modul->beschlussdatum) : _('nicht angegeben')) ?> + $modul->beschlussdatum ? date('d.m.Y', $modul->beschlussdatum) : _('nicht angegeben')) ?> </div> <div id="mvv-field-modul-fassung_nr"> <? @@ -443,7 +463,6 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { <?= $modul->kp ? htmlReady($modul->kp) : _('keine Angabe') ?> <? endif; ?> </label> - </fieldset> <fieldset class="collapsable collapsed" id="mvv-field-modul-assigned_users"> @@ -649,15 +668,16 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { ><?= htmlReady($deskriptor->ersatztext) ?></textarea> <? endif; ?> </label> + <? $default_language = array_keys($GLOBALS['CONTENT_LANGUAGES'])[0] ?> <? foreach ($deskriptor->datafields as $entry) : ?> - <? if ($entry->lang == '') : ?> - <? if (!$def_lang) : ?> + <? if (empty($entry->lang)) : ?> + <? if ($display_language !== $default_language) : ?> <? $df = new DatafieldEntryModel( [ $entry->datafield_id, $entry->range_id, $entry->sec_range_id, - $language == 'de_DE' ? '' : $language + $display_language ]); ?> <? else : ?> <? $df = $entry; ?> @@ -673,7 +693,6 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { <? endforeach; ?> </fieldset> - <input type="hidden" name="display_language" value="<?= $display_language ?>"> <footer> <? if ($deskriptor->isNew()) : ?> @@ -685,8 +704,14 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?> <? endif; ?> <? if (!$def_lang && !$deskriptor->isNew() && in_array($display_language, $translations)) : ?> - <?= Button::create(_('Löschen'), 'delete', ['title' => _('Deskriptor löschen'), 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), $GLOBALS['MVV_LANGUAGES']['values'][$display_language]['name']), - 'formaction' => $controller->action_url('delete_modul_deskriptor', $deskriptor->id, $display_language)]); ?> + <? $content_languages = $GLOBALS['CONTENT_LANGUAGES'] ?> + <?= Button::create( + _('Löschen'), + 'delete', + [ + 'title' => _('Deskriptor löschen'), + 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), $content_languages[$display_language]['name'] ?? _('unbekannt')), + 'formaction' => $controller->action_url('delete_modul_deskriptor', $deskriptor->id, $display_language)]); ?> <? endif; ?> <? endif; ?> <?= LinkButton::createCancel(_('Abbrechen'), $cancel_url, ['title' => _('zurück zur Übersicht')]) ?> @@ -694,6 +719,6 @@ if ($GLOBALS['MVV_MODUL']['SPRACHE']['default'] != $display_language) { </form> <? if (!$def_lang) : ?> <script> - jQuery('#modul_form').find('textarea, input[type=text]').after('<div style="padding-top:10px;"><a href="#" title="<?= _('Originalfassung anzeigen') ?>" class="mvv-show-original" data-type="modul"><?= Assets::img(MVV::getContentLanguageImagePath($modul->getDefaultLanguage()), ['alt' => _('Originalfassung'), 'size' => 24]) ?></a></div>'); + jQuery('#modul_form').find('textarea, input[type=text]').after('<div style="padding-top:10px;"><a href="#" title="<?= _('Originalfassung anzeigen') ?>" class="mvv-show-original" data-type="modul"><?= Assets::img(MVV::getContentLanguageImagePath($modul->original_language), ['alt' => _('Originalfassung'), 'size' => 24]) ?></a></div>'); </script> <? endif; ?> diff --git a/app/views/module/module/module.php b/app/views/module/module/module.php index d6cda88fdf11408f1d35b1f38ae29a65cde35388..839097693c279db59f0100b5e0c9e2369d21695d 100644 --- a/app/views/module/module/module.php +++ b/app/views/module/module/module.php @@ -1,3 +1,9 @@ +<?php +/** + * @var Modul[] $module + */ +?> + <? foreach ($module as $modul) : ?> <? $perm = MvvPerm::get($modul) ?> <tbody class="<?= $modul->count_modulteile ? '' : 'empty ' ?><?= $modul_id === $modul->getId() ? 'not-collapsed' : 'collapsed' ?>"> @@ -9,7 +15,7 @@ <? $details_action = $details_action ?? 'details'; ?> <a class="mvv-load-in-new-row" href="<?= $controller->action_link($details_action, $modul->getId()) ?>"> <? if ($ampel_icon) : ?> - <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?> + <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: bottom;']) ?> <? endif; ?> <?= htmlReady($modul->code) ?> </a> @@ -29,25 +35,26 @@ <? endif;?> </td> <? else : ?> - <td style="white-space:nowrap;"> + <td style="white-space:nowrap; font-weight: 700; padding-left: 20px;"> <? if ($ampel_icon) : ?> - <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: text-top;']) ?> + <?= $ampel_icon->asImg(['title' => $ampelstatus, 'style' => 'vertical-align: bottom;']) ?> <? endif; ?> <?= htmlReady($modul->code) ?> </td> - <td class="dont-hide" style="font-weight: bold;"> + <td class="dont-hide" style="font-weight: 700;"> <?= htmlReady($modul->getDisplayName()) ?> </td> <? endif; ?> <td style="text-align:center;" class="dont-hide"><?= htmlReady($modul->fassung_nr) ?></td> <td style="text-align: center;" class="dont-hide"><?= $modul->count_modulteile ?></td> - <td class="dont-hide actions" style="text-align: center;"> + <td class="dont-hide actions" style="text-align: left;"> <? if ($perm->havePermRead()) : ?> - <? $languages = $modul->deskriptoren->getAvailableTranslations(); ?> + <? $languages = $modul->deskriptoren->getAvailableTranslations($modul->original_language); ?> + <? $content_languages = $GLOBALS['CONTENT_LANGUAGES'] ?> <? foreach ($languages as $language) : ?> - <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?> <a href="<?= $controller->action_link('modul/' . $modul->id . '/', ['display_language' => $language]) ?>"> - <?= Assets::img(MVV::getContentLanguageImagePath($language), ['alt' => $lang['name'], 'size' => 24]) ?> + <?= Assets::img(MVV::getContentLanguageImagePath($language), + ['alt' => $content_languages[$language]['name'], 'size' => 24]) ?> </a> <? endforeach; ?> <? endif; ?> @@ -97,6 +104,14 @@ ['data-dialog' => ''] ) ?> <? endif; ?> + <? if ($perm->haveFieldPerm('change_language', MvvPerm::PERM_CREATE)) : ?> + <? $actionMenu->addLink( + $controller->change_languageURL($modul->id), + _('Originalsprache ändern'), + Icon::create('support', Icon::ROLE_CLICKABLE,['title' => _('Originalsprache ändern')]), + ['data-dialog' => 'size=370x270'] + ) ?> + <? endif; ?> <? if ($perm->havePermCreate()) : ?> <? $actionMenu->addButton( 'delete', diff --git a/app/views/module/module/modulteil.php b/app/views/module/module/modulteil.php index ad68edee9292c508ac416d74ba1ab72e2e4a4d7d..8e06d8049f4072e347b257e6700edda0c78d53a8 100644 --- a/app/views/module/module/modulteil.php +++ b/app/views/module/module/modulteil.php @@ -464,11 +464,15 @@ if ($GLOBALS['MVV_MODULTEIL']['SPRACHE']['default'] != $display_language) { <? else : ?> <?= Button::createAccept(_('Übernehmen'), 'store', ['title' => _('Änderungen übernehmen')]) ?> <? if (!$def_lang && !$deskriptor->isNew() && in_array($display_language, $translations)) : ?> + <? $content_languages = $GLOBALS['CONTENT_LANGUAGES'] ?> <?= Button::create( _('Löschen'), 'delete', - ['title' => _('Deskriptor löschen'), 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), $GLOBALS['MVV_LANGUAGES']['values'][$display_language]['name']), - 'formaction' => $controller->action_url('delete_modulteil_deskriptor', $deskriptor->id, $display_language) + [ + 'title' => _('Deskriptor löschen'), + 'data-confirm' => sprintf(_('Soll der Deskriptor in der Ausgabesprache %s gelöscht werden?'), + $content_languages[$display_language]['name'] ?? _('unbekannt')), + 'formaction' => $controller->action_url('delete_modulteil_deskriptor', $deskriptor->id, $display_language) ] ); ?>s <? endif; ?> diff --git a/app/views/module/module/select_module_language.php b/app/views/module/module/select_module_language.php new file mode 100644 index 0000000000000000000000000000000000000000..2f1d39d60da18d4c94caed7161ab2d6023ef3352 --- /dev/null +++ b/app/views/module/module/select_module_language.php @@ -0,0 +1,30 @@ +<?php +/** + * @var Module_ModuleController $controller + * @var array $content_languages + * @var string $default_language + */ +?> +<form class="default" action="<?= $controller->modulURL() ?>" method="post"> + <?= CSRFProtection::tokenTag() ?> + <fieldset> + <legend> + <?= _('Wählen Sie die Sprache der Originalfassung') ?> + </legend> + <label> + <?= _('Sprache') ?> + <select name="display_language"> + <option value="<?= htmlReady($default_language) ?>"> + <?= htmlReady($content_languages[$default_language]['name']) . ' (' ._('Standardsprache') . ')'?></option> + <? foreach ($content_languages as $code => $language) : ?> + <? if ($code !== $default_language) : ?> + <option value="<?= htmlReady($code) ?>"><?= htmlReady($language['name']) ?></option> + <? endif ?> + <? endforeach ?> + </select> + </label> + </fieldset> + <footer data-dialog-button> + <?= Studip\Button::createAccept(_('Modul anlegen'))?> + </footer> +</form> diff --git a/app/views/shared/deskriptor_language.php b/app/views/shared/deskriptor_language.php index 44cdb6502f3772cef416a539e7fa8377205c1558..e59f4f6934464783a45922d3f832d1dee6e5793c 100644 --- a/app/views/shared/deskriptor_language.php +++ b/app/views/shared/deskriptor_language.php @@ -1,11 +1,21 @@ -<? $table = get_class($modul) == 'Modul' ? 'mvv_modul_deskriptor' : 'mvv_modulteil_deskriptor'; ?> -<? $languages = $modul->deskriptoren->getAvailableTranslations(); ?> -<? foreach ($GLOBALS[strtoupper($table)]['SPRACHE']['values'] as $lang => $value) : ?> +<?php +/** + * @var ModulDeskriptor|ModulteilDeskriptor $descriptor + * @var string $original_language + * @var string $display_language + * @var string $link + */ +?> + +<? $languages = $descriptor->getAvailableTranslations($original_language) ?> +<? $content_languages = array_merge(array_flip($languages), $GLOBALS['CONTENT_LANGUAGES']) ?> +<? foreach ($content_languages as $code => $language) : ?> <div style="padding-top:10px;"> - <a href="<?= URLHelper::getLink($link, ['display_language' => $lang]) ?>"> - <?= Assets::img(MVV::getContentLanguageImagePath($lang), ['alt' => $value['name'], 'size' => 24]) ?> - <?= $value['name'] ?> (<?= in_array($lang, $languages) ? 'bearbeiten' : 'neu anlegen' ?>) - <?= $lang == $sprache ? Icon::create('accept', 'accept', [])->asImg() : '' ?> + <a href="<?= URLHelper::getLink($link, ['display_language' => $code]) ?>"> + <?= Assets::img(MVV::getContentLanguageImagePath($code), ['alt' => $language['name'], 'size' => 24]) ?> + <?= $language['name'] ?> (<?= ($code === $original_language ? _('Originalfassung') : '') + . (in_array($code, $languages) ? '' : _('neu')) ?>) + <?= $code === $display_language ? Icon::create('accept', Icon::ROLE_ACCEPT) : '' ?> </a> </div> -<? endforeach; ?> +<? endforeach ?> diff --git a/app/views/shared/modul/_modullv.php b/app/views/shared/modul/_modullv.php index 99c41807e4bff80c0b4a6805478f36fecb0eadc5..70ffd64d556eecbaca1737123a37e0506af48f70 100644 --- a/app/views/shared/modul/_modullv.php +++ b/app/views/shared/modul/_modullv.php @@ -5,7 +5,7 @@ <? $modulTeilSumme = $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> @@ -30,7 +30,7 @@ <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> - </tr> + </tr> <tr> <td style="width: 30%;"><strong><?= _('Workload insgesamt') ?></strong></td> <td style="width: 70%;"><?= $modulTeilSumme ?></td> diff --git a/app/views/shared/modul/description.php b/app/views/shared/modul/description.php index 59512bd94ea5c5b7f21481c55fb3e42651900210..758760dd769868b0afd23047f70491872bbc21db 100644 --- a/app/views/shared/modul/description.php +++ b/app/views/shared/modul/description.php @@ -1,7 +1,15 @@ +<?php +/** + * @var Modul $modul + * @var int $type + * @var Shared_ModulController $controller + */ +?> + <? if (count($modul->deskriptoren) > 1): ?> <div style="width: 100%; text-align: right;"> - <? foreach ($modul->deskriptoren->getAvailableTranslations() as $language) : ?> - <? $lang = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]; ?> + <? 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]) ?>"> <?= Assets::img(MVV::getContentLanguageImagePath($language), ['alt' => $lang['name'], 'size' => 24]) ?> </a> @@ -19,4 +27,4 @@ <? endif; ?> <? if ($type === 3) : ?> <?= $this->render_partial('shared/modul/_modul_ohne_lv') ?> -<? endif; ?> \ No newline at end of file +<? endif; ?> diff --git a/app/views/shared/modul/overview.php b/app/views/shared/modul/overview.php index 4bfd71efced6e1bfeaf1ad9de008c0e0504e1b02..be91c7a6a181d4f3470fd995a6d84d55e4f0b65e 100644 --- a/app/views/shared/modul/overview.php +++ b/app/views/shared/modul/overview.php @@ -1,3 +1,15 @@ +<?php +/** + * @var Modul $modul + * @var Institute $institut + * @var ModulDeskriptor $deskriptor + * @var array $modulteile + * @var Semester $semester + * @var string $pruef_ebene + * @var int $type + */ +?> + <table class="default mvv-modul-details nohover"> <tr> <th class="mvv-modul-details-head" style="width: 30%"><?= htmlReady($modul->code) ?></th> @@ -34,10 +46,10 @@ <tr> <td colspan="4" style="padding: 0;"> <table class="default nohover"> - <? if (mb_strlen($teilnahmeVoraussetzung) > 0): ?> + <? if (mb_strlen($deskriptor->voraussetzung) > 0): ?> <tr> <td style="width: 20%; font-weight: bold;"><?= _('Teilnahmevoraussetzungen') ?></td> - <td ><?= formatReady($teilnahmeVoraussetzung) ?></td> + <td ><?= formatReady($deskriptor->voraussetzung) ?></td> </tr> <? endif; ?> <? if (mb_strlen($deskriptor->kommentar)) : ?> @@ -104,7 +116,7 @@ <th><?= _('Prüfungsleistung') ?></th> <? endif; ?> </tr> - <? foreach ($modulTeile as $modul_teil): ?> + <? foreach ($modulteile as $modul_teil): ?> <tr> <? if ($type === 1): ?> <td> diff --git a/config/mvv_config.php b/config/mvv_config.php index dae7c5d7c15e6bcbf36518b2036a2694372a182a..79ee9157bfb9d61120108c3f9d186b5ada8700c3 100644 --- a/config/mvv_config.php +++ b/config/mvv_config.php @@ -114,17 +114,6 @@ $GLOBALS['MVV_MODUL']['INSTITUT_GRUPPEN'] = [ ] ]; -// Moduldeskriptor Ausgabesprache -$GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE'] = [ - 'values' => [ - 'DE' => ['visible' => 1, 'name' => _('Originalfassung'), 'content_language' => 'de_DE'], - 'EN' => ['visible' => 1, 'name' => _('Englisch'), 'content_language' => 'en_GB'] - // 'de_DE' => array('visible' => 1, 'name' => _('Originalfassung')), - // 'en_GB' => array('visible' => 1, 'name' => _('Englisch')) - ], - 'default' => 'DE' -]; - // Modulteile $GLOBALS['MVV_MODULTEIL']['NUM_BEZEICHNUNG'] = [ 'values' => [ @@ -201,9 +190,6 @@ $GLOBALS['MVV_MODULTEIL']['LERNLEHRFORM'] = [ 'default' => '' ]; -// Modulteildeskriptor -$GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE'] = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']; - // Maximale Anzahl Fachsemester $GLOBALS['MVV_MODULTEIL_FACHSEMESTER'] = 10; @@ -230,16 +216,6 @@ $GLOBALS['MVV_STGTEILVERSION']['STATUS'] = $GLOBALS['MVV_MODUL']['STATUS']; $GLOBALS['MVV_STGTEIL']['STATUS'] = $GLOBALS['MVV_MODUL']['STATUS']; -$GLOBALS['MVV_LANGUAGES'] = [ - 'values' => [ - 'DE' => ['visible' => 1, 'name' => _('Deutsch'), - 'locale' => 'de_DE'], - 'EN' => ['visible' => 1, 'name' => _('Englisch'), - 'locale' => 'en_GB'] - ], - 'default' => 'DE' -]; - $GLOBALS['MVV_STUDIENGANG']['FASSUNG_TYP'] = $GLOBALS['MVV_STGTEILVERSION']['FASSUNG_TYP']; $GLOBALS['MVV_STUDIENGANG']['STUDYCOURSE_TYPE'] = [ diff --git a/db/migrations/6.0.37_step_4261.php b/db/migrations/6.0.37_step_4261.php new file mode 100644 index 0000000000000000000000000000000000000000..13a7474c860b1b59fb4e7bfb02a78d2a91ca0276 --- /dev/null +++ b/db/migrations/6.0.37_step_4261.php @@ -0,0 +1,64 @@ +<?php + +final class Step4261 extends Migration +{ + public function description() + { + return 'Add field to module table to store original language.'; + } + + protected function up() + { + $db = DBManager::get(); + + // retrieve default language from config + $config_language = $db->fetchColumn( + "SELECT `value` FROM `config` WHERE `field` = 'DEFAULT_LANGUAGE'" + ); + $default_language = $config_language ?? array_keys($GLOBALS['CONTENT_LANGUAGES'])[0] ?? 'de_DE'; + $db->execute( + 'ALTER TABLE `mvv_modul` + ADD `original_language` VARCHAR(10) NOT NULL DEFAULT ? COLLATE latin1_bin AFTER `verantwortlich`', + [$default_language] + ); + + // use full language code for file refs + foreach ($GLOBALS['CONTENT_LANGUAGES'] as $code => $language) { + $old_code = mb_strtoupper(mb_strstr($code, '_', true)); + $db->execute('UPDATE `mvv_files_filerefs` SET `file_language` = ? WHERE `file_language` = ?', + [$code, $old_code]); + } + + $query = "INSERT INTO `config` (`field`, `value`, `type`, `range`, `section`, `mkdate`, `chdate`, `description`) + VALUES ('MVV_DEFAULT_LANGUAGE', ?, 'string', 'global', 'mvv', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), ?)"; + $db->execute($query, + [ + $default_language, + 'Code der Inhalts-Sprache, die als Original-Sprache der Deskriptoren für Module und Modulteile vorausgewählt ist.', + ] + ); + } + + protected function down() + { + $db = DBManager::get(); + + $db->exec( + "ALTER TABLE `mvv_modul` + DROP COLUMN `original_language`" + ); + + // use short language code for file refs + foreach ($GLOBALS['CONTENT_LANGUAGES'] as $code => $language) { + $old_code = mb_strtoupper(mb_strstr($code, '_', true)); + $db->execute('UPDATE `mvv_files_filerefs` SET `file_language` = ? WHERE `file_language` = ?', + [$old_code, $code]); + } + + $query = "DELETE `config`, `config_values` + FROM `config` + LEFT JOIN `config_values` USING (`field`) + WHERE `field` = 'MVV_DEFAULT_LANGUAGE'"; + $db->exec($query); + } +} diff --git a/lib/classes/MVV.php b/lib/classes/MVV.php index b4d9edf6eec9101e18662df2e4f16eaec1332145..934195b2b482a3ace1f7a55a645a7e84d30d2396 100644 --- a/lib/classes/MVV.php +++ b/lib/classes/MVV.php @@ -834,7 +834,7 @@ class MVV implements Loggable { } /** - * Returns imagepath for given language, used by MVV + * Returns image path for given language, used by MVV * First tries $GLOBALS['CONTENT_LANGUAGES'], if not defined returns hardcoded path * * @param string $language e.g. 'DE' @@ -842,8 +842,9 @@ class MVV implements Loggable { */ public static function getContentLanguageImagePath($language): string { - $content_language = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language]['content_language']; - return 'languages/' . ($GLOBALS['CONTENT_LANGUAGES'][$content_language]['picture'] ?? 'lang_' . mb_strtolower($language) . '.gif'); + $code = strtok($language, '_'); + return '/images/languages/' + . ($GLOBALS['CONTENT_LANGUAGES'][$language]['picture'] ?? 'lang_' . mb_strtolower($code) . '_text.svg'); } } diff --git a/lib/classes/globalsearch/GlobalSearchModules.php b/lib/classes/globalsearch/GlobalSearchModules.php index b9f872011409a4f13194d0488549b68783b7bc2f..f4f277f242a553bf31e8a62dc3e408b8bdd95ae9 100644 --- a/lib/classes/globalsearch/GlobalSearchModules.php +++ b/lib/classes/globalsearch/GlobalSearchModules.php @@ -35,7 +35,7 @@ class GlobalSearchModules extends GlobalSearchModule // Get language $language = ModuleManagementModel::getLanguage(); if (!$language) { - ModuleManagementModel::setLanguage($_SESSION['_language']); + ModuleManagementModel::setContentLanguage($_SESSION['_language']); $language = ModuleManagementModel::getLanguage(); } diff --git a/lib/models/Lvgruppe.php b/lib/models/Lvgruppe.php index 5e9eb7bef4780404d94bbd6d720c5cd08cdcdcbd..6f82215dd460fa6ab8808b4a82236f8fa86efd40 100644 --- a/lib/models/Lvgruppe.php +++ b/lib/models/Lvgruppe.php @@ -583,9 +583,7 @@ class Lvgruppe extends ModuleManagementModelTreeItem $modul = Modul::find($modul_id); if ($modul) { $name = $modul->responsible_institute->institute->getShortName(); - $short_name_modul = $modul->getDeskriptor( - $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['default']) - ->bezeichnung_kurz; + $short_name_modul = $modul->getDeskriptor()->bezeichnung_kurz; $name .= $short_name_modul ? ' ' . $short_name_modul : ''; } * @@ -594,7 +592,6 @@ class Lvgruppe extends ModuleManagementModelTreeItem $modulteil = Modulteil::findCached($modulteil_id); if ($modulteil) { $name = $modulteil->getDeskriptor()->bezeichnung; - //$name = $name_modulteil ? ' ' . $name_modulteil : ''; } return $name; } diff --git a/lib/models/Modul.php b/lib/models/Modul.php index 31f4bbec7f0f775d296d3862dcec2598f550de66..b6410b2bda7ac1c89e80855ee8e930193d0fb266 100644 --- a/lib/models/Modul.php +++ b/lib/models/Modul.php @@ -36,6 +36,7 @@ * @property string|null $stat database column * @property string|null $kommentar_status database column * @property string|null $verantwortlich database column + * @property string $original_language database column * @property string $author_id database column * @property string $editor_id database column * @property int $mkdate database column @@ -383,14 +384,12 @@ class Modul extends ModuleManagementModelTreeItem * previously set by ApplicationSimpleORMap::setLanguage() or the one * defined as default in mvv_config.php. */ - private function setDefaultLanguage() + private function setDefaultLanguage(): void { - if (isset($GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'] - [ModuleManagementModel::getLanguage()])) { - $this->default_language = ModuleManagementModel::getLanguage(); + if ($this->isNew()) { + $this->default_language = Config::get()->MVV_DEFAULT_LANGUAGE; } else { - $this->default_language = - $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['default']; + $this->default_language = $this->original_language; } } @@ -405,18 +404,13 @@ class Modul extends ModuleManagementModelTreeItem } /** - * Returns the Deskriptor in the given language. A Modul has always a - * Deskriptor in the default language. If the given language is unknown, the - * method returns the deskriptor in the default language. + * Returns the descriptor. If this component has no descriptor already + * a new one is created and returned. * - * @param string $language The id of the language - * @param bool If true returns always a new descriptor - * @return object The Deskriptor. + * @return ModulDeskriptor The descriptor. */ - public function getDeskriptor($language = null, $force_new = false) { - if (!isset($GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['values'][$language])) { - $language = $this->default_language; - } + public function getDeskriptor() + { if (!$this->deskriptoren) { // the module is new and has no descriptor // return a new descriptor in the default language @@ -481,7 +475,7 @@ class Modul extends ModuleManagementModelTreeItem /** * Assignes languages of instruction to this part-module. * - * @param type $languages An array of language keys defined in mvv_config.php. + * @param array $languages An array of language keys defined in mvv_config.php. */ public function assignLanguagesOfInstruction($languages) { diff --git a/lib/models/ModulDeskriptor.php b/lib/models/ModulDeskriptor.php index 5a3d07152cf27d030a2179dcbb685d3dde9b4bed..096d2d652aff65c2f0d7e13128aff00a3d1df0b0 100644 --- a/lib/models/ModulDeskriptor.php +++ b/lib/models/ModulDeskriptor.php @@ -140,12 +140,13 @@ class ModulDeskriptor extends ModuleManagementModel * @see ModuleManagementModel::getVariant() * @return string The language identifier. */ - public function getVariant() + public function getVariant(): string { - if (self::getLanguage() == $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['default']) { + if (self::getLanguage() === Config::get()->MVV_DEFAULT_LANGUAGE) { return ''; } - return self::getLanguage(); + $splitted_code = explode('_', self::getLanguage()); + return mb_strtoupper($splitted_code[0] ?? ''); } /** @@ -156,7 +157,6 @@ class ModulDeskriptor extends ModuleManagementModel */ public function deleteTranslation($language) { - $locale = $GLOBALS['MVV_LANGUAGES']['values'][$language]['locale']; - return I18NString::removeAllTranslations($this->id, 'mvv_modul_deskriptor', $locale); + return I18NString::removeAllTranslations($this->id, 'mvv_modul_deskriptor', $language); } } diff --git a/lib/models/ModuleManagementModel.php b/lib/models/ModuleManagementModel.php index 608a0884a7f3f2d5da04a0a61db8a1b63eea8608..e8f684d400cb5df8156959dd12065cfad68f60f9 100644 --- a/lib/models/ModuleManagementModel.php +++ b/lib/models/ModuleManagementModel.php @@ -699,57 +699,42 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage /** * Sets the language for localized fields and the locale environment * globally. - * Possible values are configured in mvv_config.php. + * See configuration of CONTENT_LANGUAGES. * * @see mvv_config.php - * @param string $language The language. + * @param string $language The language code. */ - public static final function setLanguage($language) + public static final function setContentLanguage($language) { - $language = mb_strtoupper(mb_strstr($language . '_', '_', true)); - if (isset($GLOBALS['MVV_LANGUAGES']['values'][$language])) { - $locale = $GLOBALS['MVV_LANGUAGES']['values'][$language]['locale']; - setLocaleEnv($locale); - self::setContentLanguage($language); - // load config file again - require $GLOBALS['STUDIP_BASE_PATH'] . '/config/mvv_config.php'; - } - } - - /** - * Switches the content to the given language. - * Compared to ModuleManagementModel::setLanguage() strings translated with - * gettext are always in the prefered language selected by the user. - * - * @param string $language The language code (see mvv_config.php) - */ - public static function setContentLanguage($language) - { - if (!is_array($GLOBALS['MVV_LANGUAGES']['values'][$language])) { + $content_languages = Config::get()->CONTENT_LANGUAGES; + if (empty($content_languages[$language])) { throw new InvalidArgumentException(); } - $locale = $GLOBALS['MVV_LANGUAGES']['values'][$language]['locale']; - I18NString::setContentLanguage($locale); + setLocaleEnv($language); + I18NString::setContentLanguage($language); self::$language = $language; + // load config file again + require $GLOBALS['STUDIP_BASE_PATH'] . '/config/mvv_config.php'; } - public function getAvailableTranslations() + public function getAvailableTranslations(string $original_language): array { - $translations[] = $GLOBALS['MVV_LANGUAGES']['default']; + $translations = []; $stmt = DBManager::get()->prepare('SELECT DISTINCT `lang` ' . 'FROM i18n ' . 'WHERE `object_id` = ? AND `table` = ?'); $stmt->execute([$this->id, $this->db_table()]); - foreach ($stmt->fetchAll() as $locale) { - $language = mb_strtoupper(mb_strstr($locale['lang'], '_', true)); - if (is_array($GLOBALS['MVV_LANGUAGES']['values'][$language])) { - $translations[] = $language; + $languages = array_merge([$original_language], + $stmt->fetchAll(PDO::FETCH_COLUMN)); + $content_languages = $GLOBALS['CONTENT_LANGUAGES']; + foreach ($languages as $code) { + if (!empty($content_languages[$code])) { + $translations[] = $code; } } return $translations; } - /** * Returns the currently selected language. * diff --git a/lib/models/Modulteil.php b/lib/models/Modulteil.php index 3b8f146de6fc2138bd2a38754e8f480976f4e080..5c769f8b9c048bf20af7f13ec8bd049358e73912 100644 --- a/lib/models/Modulteil.php +++ b/lib/models/Modulteil.php @@ -114,7 +114,11 @@ class Modulteil extends ModuleManagementModelTreeItem { parent::__construct($id); $this->object_real_name = _('Modulteil'); - $this->default_language = $GLOBALS['MVV_MODUL_DESKRIPTOR']['SPRACHE']['default']; + if ($this->modul) { + $this->default_language = $this->modul->original_language; + } else { + $this->default_language = Config::get()->MVV_DEFAULT_LANGUAGE; + } } /** @@ -165,7 +169,7 @@ class Modulteil extends ModuleManagementModelTreeItem public function getDisplayName() { - $deskriptor = $this->getDeskriptor(self::getLanguage()); + $deskriptor = $this->getDeskriptor(); $template = Config::get()->MVV_TEMPLATE_NAME_MODULTEIL; if (trim($template)) { $placeholders = [ @@ -210,19 +214,12 @@ class Modulteil extends ModuleManagementModelTreeItem } /** - * Returns the Deskriptor in the given language. A Modul has always a - * Deskriptor in the default language. If the given language is unknown, the - * method returns the deskriptor in the default language. + * Returns the descriptor. If this component has no descriptor already + * a new one is created and returned. * - * @param string $language The id of the language - * @param bool If true returns always a new descriptor - * @return object The Deskriptor. + * @return ModulteilDeskriptor The descriptor. */ - public function getDeskriptor($language = null, $force_new = false) { - if (!isset($GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['values'][$language])) { - $language = $this->default_language; - } - + public function getDeskriptor() { if (!$this->deskriptoren) { // the module is new and has no descriptor // return a new descriptor in the default language diff --git a/lib/models/ModulteilDeskriptor.php b/lib/models/ModulteilDeskriptor.php index aa6ddf7054bd7b287a30cc347c6c85fce0c9368e..26c38a161e28cef97e9ffdc6f577f889f54674c1 100644 --- a/lib/models/ModulteilDeskriptor.php +++ b/lib/models/ModulteilDeskriptor.php @@ -114,12 +114,13 @@ class ModulteilDeskriptor extends ModuleManagementModel * @see ModuleManagementModel::getVariant() * @return string The language identifier. */ - public function getVariant() + public function getVariant(): string { - if (self::getLanguage() == $GLOBALS['MVV_MODULTEIL_DESKRIPTOR']['SPRACHE']['default']) { + if (self::getLanguage() === Config::get()->MVV_DEFAULT_LANGUAGE) { return ''; } - return self::getLanguage(); + $splitted_code = explode('_', self::getLanguage()); + return mb_strtoupper($splitted_code[0] ?? ''); } /** @@ -130,7 +131,6 @@ class ModulteilDeskriptor extends ModuleManagementModel */ public function deleteTranslation($language) { - $locale = $GLOBALS['MVV_LANGUAGES']['values'][$language]['locale']; - return I18NString::removeAllTranslations($this->id, 'mvv_modulteil_deskriptor', $locale); + return I18NString::removeAllTranslations($this->id, 'mvv_modulteil_deskriptor', $language); } } diff --git a/lib/navigation/MVVNavigation.php b/lib/navigation/MVVNavigation.php index 4aab8edfdbf1a179476a87a357a2c40952782d27..ebc4833455cd4dc17be422adf00645ab03de6d08 100644 --- a/lib/navigation/MVVNavigation.php +++ b/lib/navigation/MVVNavigation.php @@ -59,6 +59,9 @@ class MVVNavigation extends Navigation $modul_navigation->addSubNavigation('module', new Navigation(_('Module'), 'dispatch.php/module/module')); + $modul_navigation->addSubNavigation('institutes', + new Navigation(_('Verantwortliche Einrichtungen'), + 'dispatch.php/module/institute/index')); $this->addSubNavigation('module', $modul_navigation); $lvg_navigation = new Navigation(_('LV-Gruppen'));