diff --git a/CHANGES.md b/CHANGES.md index f81e1dbfb..17bd6a1a3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # OPUS 4 Change Log +## Release 4.10 - 2026-05-12 + +OPUS 4.10 Project on GitHub +https://github.com/orgs/OPUS4/projects/74 + ## Release 4.9 - 2026-04-14 OPUS 4.9 Project on GitHub diff --git a/README.md b/README.md index 91c6eb755..2c5dd05a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ mostly. ## OPUS 4 -The current version of OPUS 4 is __4.9__. It is available on the [master][MASTER] branch and compatible with +The current version of OPUS 4 is __4.10__. It is available on the [master][MASTER] branch and compatible with PHP 8.1 to 8.2. PHP 8.3 and beyond are not supported yet. [Documentation][DOC] diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6f66e43a7..ce1ef9993 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,69 @@ # OPUS 4 Release Notes +## Release 4.10 - 2026-05-12 + +Der neue Release bringt insbesondere Veränderungen bei der Sprachverwaltung und +den Optionen, die in der Administration editierbar sind. Weiterhin gab es eine +Reihe kleinerer Fehlerbehebungen. + +### Update auf OPUS 4.10 + +Das Updateskript, `bin/update.sh`, muss ausgeführt werden, da es Änderungen an +der Datenbank und weitere Updateschritte gibt. + +- Tabelle `configuration` wird angelegt +- Tabelle `languages` wird entfernt +- Konfiguration in `config.xml` with in die Datenbank übertragen und die + Datei optional gelöscht +- Aktive Sprachen werden in neue Konfigurationsoptionen übernommen + +### Sprachverwaltung + +Die Sprachverwaltung wurde aus der Administration entfernt. Dafür werden jetzt +485 ISO 639 Sprachen im Standard unterstützt. Welche Sprachen in den Formularen +zur Auswahl stehen sollen, lässt sich über Optionen einstellen. + +Mehr dazu findet sich im OPUS 4 Handbuch unter +https://www.opus-repository.org/userdoc/admin/languages.html + +Beim Update werden die aktiven Sprachen automatisch in die neue Konfiguration +übernommen. + +### Konfiguration + +Bislang sind nur wenige Optionen in der Administration editierbar. Diese wurde +bisher in `application/configs/config.xml` gespeichert. Dafür gibt es jetzt eine +Tabelle in der Datenbank. Beim Update wird der Inhalt von `config.xml` in die +Datenbank übertragen und die Datei dann (optional) gelöscht. + +Die editierbaren Optionen werden nun in `application/configs/options.yml` +definiert. Generell kann die Liste lokal erweitert werden. Im Standard werden +im Laufe der Zeit mehr Optionen in der Weboberfläche verfügbar gemacht werden. + +### RSS-Links + +RSS-Links können nun ausgeblendet werden. Sie werden automatisch ausgeblendet, +wenn ein User keinen Zugriff auf das RSS-Modul hat. + + rss.showLinks = 0 + +### DeepGreen Client + +Es gibt zwei neue Optionen, die steuern wie beim Import von Dokumenten mit +nicht erlaubten Dateitypen umgegangen werden soll. + + deepgreen.import.importAllFiles = 0 + deepgreen.import.importSupportedFiles = 1 + +Wenn **importAllFiles** aktiviert ist, werden alle Dateien importiert. Sollen +nur die in der OPUS 4 Konfiguration erlaubt Dateitypen importiert werden, kann +**importSupportedFiles** aktiviert werden. Sind beide Optionen deaktiviert, +werden Dokumente mit nicht erlaubten Dateitypen nicht importiert. Es geplant +in diesen Fällen in Zukunft Benachrichtigungen in der Administration anzuzeigen +und die Konfigurationsmöglichkeiten weiter auszubauen. + +-- + ## Release 4.9 - 2026-04-14 ### Unterstützte PHP-Versionen diff --git a/application/configs/application.ini b/application/configs/application.ini index 9e941e643..093d6ffe7 100644 --- a/application/configs/application.ini +++ b/application/configs/application.ini @@ -61,7 +61,11 @@ db.debug = 0 ; LOCALE SETTINGS resources.locale.default = 'de' -; SUPPORTED LANGUAGES +; Languages selectable for documents +i18n.languages.active = deu, eng, fra, rus, spa, mul +i18n.languages.sortByName = 0 + +; SUPPORTED USER INTERFACE LANGUAGES supportedLanguages = de,en ;GENERAL SETTINGS @@ -70,7 +74,7 @@ name = 'OPUS 4' logoLink = home security = 1 workspacePath = APPLICATION_PATH "/workspace" -version = 4.9 +version = 4.10 update.latestVersionCheckUrl = "https://api.github.com/repos/opus4/application/releases/latest" snippets.basePath = APPLICATION_PATH "/scripts/snippets" @@ -250,6 +254,7 @@ search.index.enrichment.blacklist = 'opus_doi_json' ; RSS Feed rss.maxDocs = 100 +rss.showLinks = 1 ;DOCTYPE VALIDATION SCHEMA FILE ; TODO determine path dynamically (does this belong into the framework) @@ -761,6 +766,9 @@ console.commandProvider[] = "Opus\Import\Console\ImportCommandProvider" ; DeepGreen configuration deepgreen.configFile = APPLICATION_PATH'/application/configs/deepgreen.ini' +deepgreen.import.importAllFiles = 0 +deepgreen.import.importSupportedFiles = 1 + ; Staging, Testing and Development configurations ===================================================================== [staging : production] diff --git a/application/configs/navigationModules.xml b/application/configs/navigationModules.xml index 9f00eac02..ce1a1cf7c 100644 --- a/application/configs/navigationModules.xml +++ b/application/configs/navigationModules.xml @@ -364,50 +364,6 @@ - - mvc - - admin_title_languages_description - group-cafelatte - admin - language - index - languages - - - mvc - - admin - language - show - - - - mvc - - admin - language - new - - - - mvc - - admin - language - edit - - - - mvc - - admin - language - delete - - - - mvc diff --git a/application/configs/options.yml b/application/configs/options.yml new file mode 100644 index 000000000..b4c1e7851 --- /dev/null +++ b/application/configs/options.yml @@ -0,0 +1,44 @@ +# +# Defines options available in administration user interface (Settings->Options). +# +# The 'type' defines how the option appears in the form. Supported types are +# - string (default) +# - int +# - bool +# +# The 'section' allows grouping options. The names are arbitrary and are used as section +# labels if no translations for the section exist. +# +# 'options' can be used to pass additional options to the form element, for +# instance to increase the size. +# +# The translation keys for options use the following patterns: +# - admin_config_section_SECTIONNAME +# - admin_config_OPTIONKEY +# - admin_config_OPTIONKEY_description +# +# For instance: +# - admin_config_section_languages +# - admin_config_i18n.languages.active +# - admin_config_i18n.languages.active_description +# + +searchengine.solr.parameterDefaults.rows: + type: int + section: searching + options: + min: 10 + +browsing.series.sortByTitle: + type: bool + section: browsing + +i18n.languages.active: + type: string + section: languages + options: + size: 60 + +i18n.languages.sortByName: + type: bool + section: languages diff --git a/bin/install.sh b/bin/install.sh index 9faf92435..86ed33af6 100755 --- a/bin/install.sh +++ b/bin/install.sh @@ -174,7 +174,7 @@ do fi done -php "$BASEDIR/scripts/change-password.php" admin "$ADMIN_PWD" +php "$BASEDIR/bin/opus4" account:setpwd admin -p "$ADMIN_PWD" # # Configure Solr connection diff --git a/build.xml b/build.xml index 02445f212..43962e401 100644 --- a/build.xml +++ b/build.xml @@ -316,9 +316,11 @@ - - + + + + diff --git a/composer.json b/composer.json index 787b8eaa2..f80e6a7a9 100644 --- a/composer.json +++ b/composer.json @@ -23,17 +23,18 @@ "ext-yaml": "*", "opus4/zf1-future": "1.25.*", "jpgraph/jpgraph": "dev-master", - "opus4-repo/opus4-common": "^4.9", - "opus4-repo/framework": "^4.9", + "opus4-repo/opus4-common": "^4.10", + "opus4-repo/framework": "^4.10", "opus4-repo/search": "^4.9", - "opus4-repo/opus4-bibtex": "^4.9", - "opus4-repo/opus4-import": "^4.9", + "opus4-repo/opus4-bibtex": "^4.10", + "opus4-repo/opus4-import": "^4.10", "opus4-repo/opus4-pdf": "^4.9", "opus4-repo/opus4-job": "^4.9", "opus4-repo/opus4-security": "^4.9", "opus4-repo/opus4-sword": "^4.9", - "opus4-repo/opus4-app-common": "^4.9", - "opus4-repo/opus4-deepgreen": "^4.9", + "opus4-repo/opus4-app-common": "^4.10", + "opus4-repo/opus4-deepgreen": "^4.10", + "opus4-repo/opus4-i18n": "^4.10", "components/jquery": "3.4.*", "components/jqueryui": "1.12.*", "oomphinc/composer-installers-extender": "^2.0", diff --git a/db/masterdata/002_create_languages.sql b/db/masterdata/002_create_languages.sql deleted file mode 100644 index 6f44a3bd6..000000000 --- a/db/masterdata/002_create_languages.sql +++ /dev/null @@ -1,44 +0,0 @@ --- MySQL dump 10.11 --- --- Server version 5.0.67-0ubuntu6 - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Dumping data for table `languages` --- Based on http://sil.org/iso639-3/iso-639-3_20090210.tab --- - -LOCK TABLES `languages` WRITE; -/*!40000 ALTER TABLE `languages` DISABLE KEYS */; -INSERT INTO `languages` (`id`, `part2_b`, `part2_t`, `part1`, `scope`, `type`, `ref_name`, `comment`, `active`) VALUES -('1','ger','deu','de','I','L','German','',1), -('2','eng','eng','en','I','L','English','',1), -('3','ita','ita','it','I','L','Italian','',0), -('4','fre','fra','fr','I','L','French','',1), -('5','por','por','pt','I','L','Portuguese','',0), -('6','rus','rus','ru','I','L','Russian','',1), -('7','spa','spa','es','I','L','Spanish','',1), -('8','mul','mul','','I','L','Multiple languages','',1); -/*!40000 ALTER TABLE `languages` ENABLE KEYS */; -UNLOCK TABLES; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2009-04-09 8:56:35 diff --git a/db/masterdata/022-set-opus-version.sql b/db/masterdata/022-set-opus-version.sql index 9af826166..d2316260f 100644 --- a/db/masterdata/022-set-opus-version.sql +++ b/db/masterdata/022-set-opus-version.sql @@ -11,7 +11,7 @@ START TRANSACTION; -- Set internal OPUS version (for controlling updates) TRUNCATE TABLE `opus_version`; -INSERT INTO `opus_version` (`version`) VALUES (20); +INSERT INTO `opus_version` (`version`) VALUES (22); COMMIT; diff --git a/library/Application/Bootstrap.php b/library/Application/Bootstrap.php index 4ed1957ab..d3b1d2783 100644 --- a/library/Application/Bootstrap.php +++ b/library/Application/Bootstrap.php @@ -30,9 +30,11 @@ */ use Opus\App\Common\Configuration; +use Opus\Common\Config; use Opus\Common\Log\LogService; use Opus\Common\Repository; use Opus\Db\DatabaseBootstrap; +use Opus\Db2\Configuration as ConfigurationDatabase; use Opus\Search\Plugin\Index; /** @@ -258,7 +260,7 @@ protected function _setupPageCache() */ protected function _initTranslation() { - $this->bootstrap(['Configuration', 'Session', 'Logging', 'ZendCache']); + $this->bootstrap(['Configuration', 'OnlineConfiguration', 'Session', 'Logging', 'ZendCache']); $logService = LogService::getInstance(); $logger = $logService->getLog('translation'); @@ -411,4 +413,15 @@ protected function _initIndexPlugin() // TODO this is a dependency on a specific implementation (refactor to remove) $cache::setIndexPluginClass(Index::class); } + + protected function _initOnlineConfiguration() + { + $this->bootstrap('Database'); + + $configuration = new ConfigurationDatabase(); + $onlineConfig = $configuration->getConfig(); + + $config = Config::get(); + $config->merge($onlineConfig); + } } diff --git a/library/Application/Console/Admin/ChangePasswordCommand.php b/library/Application/Console/Admin/ChangePasswordCommand.php new file mode 100644 index 000000000..8b1423ac5 --- /dev/null +++ b/library/Application/Console/Admin/ChangePasswordCommand.php @@ -0,0 +1,128 @@ +--password option can be used to provide a new password without interaction, however this should be used carefully, since the password won't be hidden. +EOT; + + $this->setName('account:setpwd') + ->setDescription('Set user password') + ->setHelp($help) + ->addArgument( + self::ARGUMENT_USER, + InputArgument::REQUIRED, + 'User login' + ) + ->addOption( + self::OPTION_PASSWORD, + '-p', + InputOption::VALUE_REQUIRED, + 'New password' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $formatter = new FormatterHelper(); + + $login = $input->getArgument(self::ARGUMENT_USER); + + try { + $account = Account::fetchAccountByLogin($login); + } catch (SecurityException $e) { + $formatted = $formatter->formatBlock('User not found', 'error'); + $output->writeln($formatted); + return self::FAILURE; + } + + $password = $input->getOption(self::OPTION_PASSWORD); + + if ($password === null) { + $helper = new QuestionHelper(); + + $question = new Question('New password: '); + $question->setHidden(true); + $question->setHiddenFallback(false); + $password = $helper->ask($input, $output, $question); + + $question = new Question('Confirm password: '); + $question->setHidden(true); + $question->setHiddenFallback(false); + $confirm = $helper->ask($input, $output, $question); + + if ($password !== $confirm) { + $formatted = $formatter->formatBlock('Passwords do not match.', 'error'); + $output->writeln($formatted); + return self::FAILURE; + } + } + + try { + $account->setPassword($password)->store(); + } catch (SecurityException $e) { + $formatted = $formatter->formatBlock('Setting password failed', 'error'); + $output->writeln($formatted); + return self::FAILURE; + } + + $output->writeln('Password successfully changed.'); + + return self::SUCCESS; + } +} diff --git a/library/Application/Console/App.php b/library/Application/Console/App.php index 901f6b926..4dfd0eef0 100644 --- a/library/Application/Console/App.php +++ b/library/Application/Console/App.php @@ -74,6 +74,8 @@ public function __construct() $this->add(new Application_Console_Collection_MoveCommand()); $this->add(new Application_Console_Collection_RemoveCommand()); + $this->add(new Application_Console_Admin_ChangePasswordCommand()); + if (class_exists(TaskManager::class)) { /* Tasks commands do not work without the TaskManager. If the current PHP version is less than 7.4 diff --git a/library/Application/Controller/Action/Helper/Translation.php b/library/Application/Controller/Action/Helper/Translation.php index 17574d8c8..b92a9940c 100644 --- a/library/Application/Controller/Action/Helper/Translation.php +++ b/library/Application/Controller/Action/Helper/Translation.php @@ -31,7 +31,6 @@ use Opus\Common\Enrichment; use Opus\Document; -use Opus\Language; /** * Helper for handling translations. @@ -103,12 +102,7 @@ public function getKeyForField($modelName, $fieldName) $translationKey = $this->normalizeModelName($modelName) . '_' . $fieldName; return preg_replace('/Opus_Common_/', 'Opus_', $translationKey); // TODO LAMINAS fix keys } else { - switch ($modelName) { - case Language::class: - return $this->normalizeModelName($modelName) . '_' . $fieldName; - default: - return $fieldName; - } + return $fieldName; } } diff --git a/library/Application/Form/Element/Language.php b/library/Application/Form/Element/Language.php index acfe7e09f..7089bc0d7 100644 --- a/library/Application/Form/Element/Language.php +++ b/library/Application/Form/Element/Language.php @@ -29,7 +29,10 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ -use Opus\Common\Language; +use Opus\App\Common\Configuration; +use Opus\Common\Log; +use Opus\I18n\I18nException; +use Opus\I18n\Languages; /** * TODO override setLabel for more robust translation @@ -52,6 +55,31 @@ public function init() } } + /** + * @param string|null $value + * @return void + */ + public function setValue($value) + { + if ($value !== null) { + $language = Languages::getLanguage($value); + + if (null !== $language) { + $value = $language->getId(); + } + } + + if (! in_array($value, array_keys(self::getLanguageList()))) { + $label = Locale::getDisplayName($value); + if ($label !== $value) { + $label .= " ({$value})"; + } + $this->addMultiOption($value, $label); + } + + parent::setValue($value); + } + /** * @return array */ @@ -65,15 +93,68 @@ public static function getLanguageList() /** * Setup language list. + * + * TODO reduce responsibilities of this function */ public static function initLanguageList() { + $config = Configuration::getInstance()->getConfig(); + + if (! isset($config->i18n->languages->active)) { + throw new Exception('no active languages configured'); + } + + $optionValue = $config->i18n->languages->active; + + if (strlen(trim($optionValue)) > 0) { + // Use configured languages + $activeLanguages = explode(',', $optionValue); + } else { + // Use all languages + $helper = new Languages(); + $activeLanguages = array_keys($helper->getAllAsArray()); + } + + $activeLanguages = array_filter($activeLanguages, function ($lang) { + return ! empty($lang); + }); + + if (isset($config->i18n->languages->local)) { + $localLanguages = $config->i18n->languages->local->toArray(); + $languages = new Languages(); + try { + $languages->addLanguages($localLanguages); + } catch (I18nException $ex) { + Log::get()->err('Error loading local languages: ' . $ex->getMessage()); + } + } + $translate = Application_Translate::getInstance(); + $locale = $translate->getLocale(); + $languages = []; - foreach (Language::getAllActiveTable() as $languageRow) { - $langId = $languageRow['part2_t']; - $languages[$langId] = $translate->translateLanguage($langId); + + foreach ($activeLanguages as $lang) { + $part2b = trim($lang); + $language = Languages::getLanguage($part2b); + + if ($language === null) { + Log::get()->err("Language '{$part2b}' not found"); + continue; + } + + $langId = $language->getPart2t(); + $translation = $language->getDisplayName($locale); + + // TODO support local translations + + $languages[$langId] = $translation; } + + if (isset($config->i18n->languages->sortByName) && filter_var($config->i18n->languages->sortByName, FILTER_VALIDATE_BOOLEAN)) { + asort($languages); + } + self::$languageList = $languages; } } diff --git a/library/Application/Form/Element/SupportedLanguages.php b/library/Application/Form/Element/SupportedLanguages.php index 00392334e..72cfbecc7 100644 --- a/library/Application/Form/Element/SupportedLanguages.php +++ b/library/Application/Form/Element/SupportedLanguages.php @@ -116,7 +116,7 @@ public function getLanguageOptions() */ public function setValue($value) { - if (! is_array($value)) { + if (! is_array($value) && $value !== null) { $values = array_map('trim', explode(',', $value)); } else { $values = $value; diff --git a/library/Application/Security/AclProvider.php b/library/Application/Security/AclProvider.php index 678ba3519..3d7256192 100644 --- a/library/Application/Security/AclProvider.php +++ b/library/Application/Security/AclProvider.php @@ -65,7 +65,6 @@ class Application_Security_AclProvider 'licences', 'collections', 'series', - 'languages', 'statistics', 'institutions', 'enrichments', diff --git a/library/Application/View/Helper/DocumentAbstract.php b/library/Application/View/Helper/DocumentAbstract.php index 75b534ea7..5a0ba612b 100644 --- a/library/Application/View/Helper/DocumentAbstract.php +++ b/library/Application/View/Helper/DocumentAbstract.php @@ -30,7 +30,7 @@ */ use Opus\Common\DocumentInterface; -use Opus\Common\Language; +use Opus\I18n\Languages; /** * Helper for printing the abstract of a OPUS document. @@ -48,7 +48,7 @@ class Application_View_Helper_DocumentAbstract extends Application_View_Helper_D public function documentAbstract($document = null) { if ($this->isPreferUserInterfaceLanguage()) { - $language = Language::getPart2tForPart1(Application_Translate::getInstance()->getLocale()); + $language = Languages::getPart2t(Application_Translate::getInstance()->getLocale()); $abstract = $document->getMainAbstract($language); } else { diff --git a/library/Application/View/Helper/DocumentTitle.php b/library/Application/View/Helper/DocumentTitle.php index e62177eed..9672553d8 100644 --- a/library/Application/View/Helper/DocumentTitle.php +++ b/library/Application/View/Helper/DocumentTitle.php @@ -30,7 +30,7 @@ */ use Opus\Common\DocumentInterface; -use Opus\Common\Language; +use Opus\I18n\Languages; /** * Helper for printing the title of a OPUS document. @@ -55,7 +55,7 @@ class Application_View_Helper_DocumentTitle extends Application_View_Helper_Docu public function documentTitle($document = null) { if ($this->isPreferUserInterfaceLanguage()) { - $language = Language::getPart2tForPart1(Application_Translate::getInstance()->getLocale()); + $language = Languages::getPart2t(Application_Translate::getInstance()->getLocale()); $title = $document->getMainTitle($language); } else { diff --git a/library/Application/View/Helper/LanguageWebForm.php b/library/Application/View/Helper/LanguageWebForm.php index 2bad888c3..a102ee810 100644 --- a/library/Application/View/Helper/LanguageWebForm.php +++ b/library/Application/View/Helper/LanguageWebForm.php @@ -29,7 +29,7 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ -use Opus\Common\Language; +use Opus\I18n\Languages; /** * View helper for tranform long language form in short language form (Part2 in Part1). @@ -55,8 +55,7 @@ class Application_View_Helper_LanguageWebForm extends Zend_View_Helper_Abstract public function languageWebForm($value) { if (! array_key_exists($value, $this->langCache)) { - $lang = Language::getPropertiesByPart2T($value); - $this->langCache[$value] = $lang['part1']; + $this->langCache[$value] = Languages::getPart1($value); } return $this->langCache[$value]; } diff --git a/library/Application/View/Helper/RssLink.php b/library/Application/View/Helper/RssLink.php new file mode 100644 index 000000000..9b1e3d0c8 --- /dev/null +++ b/library/Application/View/Helper/RssLink.php @@ -0,0 +1,85 @@ +isShowRssLinks() || ! $this->isRssAllowed()) { + return ''; + } + + $view = $this->view; + + if (is_string($options)) { + $rssUrl = $options; + } else { + $basicOptions = [ + 'module' => 'rss', + 'controller' => 'index', + 'action' => 'index', + ]; + + if (is_array($options)) { + $rssUrl = $view->url(array_merge($basicOptions, $options), null, true); + } else { + $rssUrl = $view->url($basicOptions, null, true); + } + } + + $imagePath = $view->layoutPath() . '/img/feed_small.png'; + $alt = $view->translate('rss_icon'); + $title = $view->translate('rss_title'); + + $output = "" . PHP_EOL; + $output .= " \"{$alt}\"" . PHP_EOL; + $output .= ""; + + return $output; + } + + protected function isShowRssLinks(): bool + { + $config = $this->getConfig(); + return isset($config->rss->showLinks) && filter_var($config->rss->showLinks, FILTER_VALIDATE_BOOLEAN); + } + + protected function isRssAllowed(): bool + { + $realm = Realm::getInstance(); + return $realm->checkModule('rss'); + } +} diff --git a/library/Application/Form/Element/LanguageType.php b/library/Application/View/Helper/RssMetaLink.php similarity index 70% rename from library/Application/Form/Element/LanguageType.php rename to library/Application/View/Helper/RssMetaLink.php index b00fafcea..9b9ad5710 100644 --- a/library/Application/Form/Element/LanguageType.php +++ b/library/Application/View/Helper/RssMetaLink.php @@ -25,20 +25,34 @@ * along with OPUS; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * @copyright Copyright (c) 2008, OPUS 4 development team + * @copyright Copyright (c) 2026, OPUS 4 development team * @license http://www.gnu.org/licenses/gpl.html General Public License */ -class Application_Form_Element_LanguageType extends Application_Form_Element_SelectWithNull +/** + * TODO check permissions and options + * TODO unit tests + */ +class Application_View_Helper_RssMetaLink extends Application_View_Helper_RssLink { - public function init() + public function rssMetaLink(?string $rssUrl = null): string { - parent::init(); + if (! $this->isShowRssLinks() || ! $this->isRssAllowed()) { + return ''; + } - $values = ['Null', 'A', 'C', 'E', 'H', 'L', 'S']; + $view = $this->view; - foreach ($values as $value) { - $this->addMultiOption($value, 'Opus_Language_Type_Value_' . $value); + if ($rssUrl === null) { + $rssUrl = $view->baseUrl() . '/rss/index/index'; } + + $view->headLink([ + 'rel' => 'alternate', + 'type' => 'application/rss+xml', + 'href' => $view->serverUrl() . $rssUrl, + ]); + + return ''; } } diff --git a/modules/admin/controllers/ConfigController.php b/modules/admin/controllers/ConfigController.php index 167eace80..032f5bf15 100644 --- a/modules/admin/controllers/ConfigController.php +++ b/modules/admin/controllers/ConfigController.php @@ -29,8 +29,6 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ -use Opus\App\Common\Configuration; - class Admin_ConfigController extends Application_Controller_Action { public function indexAction() @@ -48,8 +46,7 @@ public function indexAction() case Admin_Form_Configuration::RESULT_SAVE: if ($form->isValid($data)) { $config = new Zend_Config([], true); - $form->updateModel($config); - Configuration::save($config); + $form->updateModel($config); // TODO $config object is not needed } else { break; } diff --git a/modules/admin/controllers/LanguageController.php b/modules/admin/controllers/LanguageController.php deleted file mode 100644 index 52e7238ea..000000000 --- a/modules/admin/controllers/LanguageController.php +++ /dev/null @@ -1,57 +0,0 @@ -setFormClass(Admin_Form_Language::class); - parent::init(); - } - - /** - * @param LanguageInterface $model - * @return bool - */ - public function isDeletable($model) - { - return ! $model->isUsed(); - } -} diff --git a/modules/admin/forms/Configuration.php b/modules/admin/forms/Configuration.php index b65dcbd60..3fb9d6375 100644 --- a/modules/admin/forms/Configuration.php +++ b/modules/admin/forms/Configuration.php @@ -33,25 +33,20 @@ /** * Form for editing selected OPUS 4 configuration options. - * - * TODO Application_Form_Abstract should be enough (not ID element needed) */ class Admin_Form_Configuration extends Application_Form_Model_Abstract { /** * Prefix for translation keys of configuration options. * - * TODO wird auf von Admin_Model_Option verwendet + * TODO wird auch von Admin_Model_Option verwendet */ public const LABEL_TRANSLATION_PREFIX = 'admin_config_'; /** @var array Configured options for form. */ private $options; - /** - * @param null|Zend_Config $config - */ - public function __construct($config = null) + public function __construct(?array $config = null) { if ($config !== null) { $options = new Admin_Model_Options($config); @@ -73,19 +68,27 @@ public function init() $this->options = $options->getOptions(); } - foreach ($this->options as $name => $option) { + foreach ($this->options as $option) { $section = $option->getSection(); + $elementOptions = $option->getOptions(); + + $translator = $this->getTranslator(); + + if ($translator->isTranslated($option->getDescription())) { + $elementOptions['description'] = $option->getDescription(); + } + + if ($translator->isTranslated($option->getLabel())) { + $elementOptions['label'] = $option->getLabel(); + } else { + $elementOptions['label'] = $option->getKey(); + } + $element = $this->createElement( $option->getElementType(), - $name, - array_merge( - [ - 'label' => $option->getLabel(), - 'description' => $option->getDescription(), - ], - $option->getOptions() - ) + $option->getElementId(), + $elementOptions ); $this->addElement($element); @@ -95,6 +98,8 @@ public function init() $this->removeElement(self::ELEMENT_MODEL_ID); $this->setAttrib('class', 'admin_config'); + + $this->sortSections(); } /** @@ -104,9 +109,9 @@ public function init() */ public function populateFromModel($config) { - foreach ($this->options as $name => $option) { + foreach ($this->options as $option) { $value = Configuration::getValueFromConfig($config, $option->getKey()); - $this->getElement($name)->setValue($value); + $this->getElement($option->getElementId())->setValue($value); } } @@ -117,15 +122,18 @@ public function populateFromModel($config) */ public function updateModel($config) { - foreach ($this->options as $name => $option) { - $value = $this->getElement($name)->getValue(); + foreach ($this->options as $option) { + $value = $this->getElement($option->getElementId())->getValue(); // TODO move into Admin_Model_Option? if (is_array($value)) { $value = implode(',', $value); } + if ($value !== null && strlen(trim($value)) === 0) { + $value = null; + } - Configuration::setValueInConfig($config, $option->getKey(), $value); + $option->setValue($value); } } @@ -134,20 +142,25 @@ public function updateModel($config) * * If necessary a new display group is created. * - * @param Zend_Form_Element $element Form element - * @param string $section Name of section * @throws Zend_Form_Exception */ - public function addElementToSection($element, $section) + public function addElementToSection(Zend_Form_Element $element, string $section): void { $group = $this->getDisplayGroup($section); + $translator = $this->getTranslator(); + $sectionKey = self::LABEL_TRANSLATION_PREFIX . 'section_' . $section; + + if (! $translator->isTranslated($sectionKey)) { + $sectionKey = ucfirst($section); + } + if ($group === null) { $this->addDisplayGroup( [$element], $section, [ - 'legend' => self::LABEL_TRANSLATION_PREFIX . 'section_' . $section, + 'legend' => $sectionKey, 'decorators' => ['FormElements', 'Fieldset'], ] ); @@ -155,4 +168,24 @@ public function addElementToSection($element, $section) $group->addElement($element); } } + + public function sortSections(): void + { + $groups = $this->getDisplayGroups(); + + $names = array_keys($groups); + unset($names['actions']); + + sort($names); + + $sorted = []; + + foreach ($names as $section) { + $sorted[$section] = $groups[$section]; + } + + $sorted['actions'] = $groups['actions']; + + $this->setDisplayGroups($sorted); + } } diff --git a/modules/admin/forms/Document/Tags.php b/modules/admin/forms/Document/Tags.php index b7ba242b5..e6ba9093c 100644 --- a/modules/admin/forms/Document/Tags.php +++ b/modules/admin/forms/Document/Tags.php @@ -30,7 +30,7 @@ */ use Opus\Common\DocumentInterface; -use Opus\Common\Language; +use Opus\I18m\Languages; /** * Unterformular fuer GND Subjects im Metadaten-Formular. @@ -186,7 +186,7 @@ public function processPost($data, $context) $lang = $data[self::ELEMENT_LANGUAGE]; if ($lang === null) { $translate = Application_Translate::getInstance(); - $lang = Language::getPart2tForPart1($translate->getLocale()); + $lang = Languages::getPart2t($translate->getLocale()); } $this->addMultipleSubjectsFromString($data[self::ELEMENT_SUBJECTS], $lang); return Admin_Form_Document::RESULT_SHOW; diff --git a/modules/admin/forms/Language.php b/modules/admin/forms/Language.php deleted file mode 100644 index b7519298a..000000000 --- a/modules/admin/forms/Language.php +++ /dev/null @@ -1,95 +0,0 @@ -setRemoveEmptyCheckbox(false); - $this->setLabelPrefix('Opus_Language_'); - $this->setUseNameAsLabel(true); - $this->setModelClass(Language::class); - - $this->addElement('checkbox', self::ELEMENT_ACTIVE); - $this->addElement('text', self::ELEMENT_REFNAME, ['required' => true]); - $this->addElement('text', self::ELEMENT_PART2T, ['required' => true]); - $this->addElement('text', self::ELEMENT_PART2B); - $this->addElement('text', self::ELEMENT_PART1); - $this->addElement('LanguageScope', self::ELEMENT_SCOPE); - $this->addElement('LanguageType', self::ELEMENT_TYPE); - $this->addElement('text', self::ELEMENT_COMMENT); - } - - /** - * @param LanguageInterface $language - */ - public function populateFromModel($language) - { - $this->getElement(self::ELEMENT_MODEL_ID)->setValue($language->getId()); - $this->getElement(self::ELEMENT_ACTIVE)->setValue($language->getActive()); - $this->getElement(self::ELEMENT_PART2B)->setValue($language->getPart2B()); - $this->getElement(self::ELEMENT_PART2T)->setValue($language->getPart2T()); - $this->getElement(self::ELEMENT_PART1)->setValue($language->getPart1()); - $this->getElement(self::ELEMENT_SCOPE)->setValue($language->getScope()); - $this->getElement(self::ELEMENT_TYPE)->setValue($language->getType()); - $this->getElement(self::ELEMENT_REFNAME)->setValue($language->getRefName()); - $this->getElement(self::ELEMENT_COMMENT)->setValue($language->getComment()); - } - - /** - * @param LanguageInterface $language - */ - public function updateModel($language) - { - $language->setActive($this->getElementValue(self::ELEMENT_ACTIVE)); - $language->setPart2B($this->getElementValue(self::ELEMENT_PART2B)); - $language->setPart2T($this->getElementValue(self::ELEMENT_PART2T)); - $language->setPart1($this->getElementValue(self::ELEMENT_PART1)); - $language->setScope($this->getElementValue(self::ELEMENT_SCOPE)); - $language->setType($this->getElementValue(self::ELEMENT_TYPE)); - $language->setRefName($this->getElementValue(self::ELEMENT_REFNAME)); - $language->setComment($this->getElementValue(self::ELEMENT_COMMENT)); - } -} diff --git a/modules/admin/language/config.tmx b/modules/admin/language/config.tmx index 98bb735bb..0ca26d1ca 100644 --- a/modules/admin/language/config.tmx +++ b/modules/admin/language/config.tmx @@ -26,7 +26,7 @@ - + Search @@ -49,29 +49,38 @@ Browsing - Browsing + Browsen + + + + + + Languages + + + Sprachen - Supported Languages + User Interface Languages - Unterstützte Sprachen + Weboberfläche Sprachen - Languages for the user interface. Select at least one. + Languages for the user interface. Select at least one (e.g. 'en'). - Sprachen für die Benutzeroberfläche. Mindestens eine auswählen. + Sprachen für die Benutzeroberfläche. Mindestens eine angeben (z.B. 'de'). - + Default search results/page @@ -80,7 +89,7 @@ - + Number of results that should be display on a single page. @@ -89,7 +98,7 @@ - + Sort series by title @@ -98,7 +107,7 @@ - + Activates alphabetical sorting of series in browsing list and publish form. @@ -107,6 +116,33 @@ + + + Selectable languages + + + Auswählbare Sprachen + + + + + + Languages selectable for a document (ISO 639). + + + Sprachen, die für ein Dokument auswählbar sind (ISO 639). + + + + + + Sort alphabetical + + + Alphabetisch sortieren + + + diff --git a/modules/admin/language/language.tmx b/modules/admin/language/language.tmx deleted file mode 100644 index 9e8f4e1aa..000000000 --- a/modules/admin/language/language.tmx +++ /dev/null @@ -1,138 +0,0 @@ - - - - -
-
- - - - - - 639-2 Identifier (bibliographic code) - - - 639-2 Bezeichner (bibliografischer Code) - - - - - - 639-2 Identifier (terminology code) - - - 639-2 Bezeichner (Terminologie-Code) - - - - - - 639-1 identifier - - - 639-1 Bezeichnung - - - - - - Scope - - - Umfang - - - - - - Type - - - Typ - - - - - - Language Name - - - Sprache - - - - - - Comment - - - Kommentar - - - - - - Active - - - Aktiv - - - - - - Store Data - - - Daten abspeichern - - - - - - Edit Language - - - Sprache ändern - - - - - - New Language - - - Neue Sprache - - - - - - Admin Languages - - - Sprachen verwalten - - - - - - Show Language - - - Sprache anzeigen - - - - - - Delete Language - - - Sprache löschen - - - - - -
diff --git a/modules/admin/language/resources.tmx b/modules/admin/language/resources.tmx index d2edd47f6..e33e644b7 100644 --- a/modules/admin/language/resources.tmx +++ b/modules/admin/language/resources.tmx @@ -34,15 +34,6 @@
- - - Manage languages - - - Sprachen verwalten - - - Manage licences diff --git a/modules/admin/models/Option.php b/modules/admin/models/Option.php index 30f61032f..3ad0af9ba 100644 --- a/modules/admin/models/Option.php +++ b/modules/admin/models/Option.php @@ -29,58 +29,53 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ +use Opus\Db2\Configuration; + class Admin_Model_Option extends Application_Model_Abstract { /** @var string Name of configuration option. */ - private $name; + private $key; /** @var array Parameters for option. */ private $config; - /** - * @param string $name Name of option - * @param array $config Parameters for option - */ - public function __construct($name, $config) + public function __construct(string $key, array $config) { - $this->name = $name; + $this->key = $key; $this->config = $config; } /** - * @return string + * Returns option key. */ - public function getName() + public function getKey(): string { - return $this->name; + return $this->key; } /** - * @return string + * Returns translation key for option label. */ - public function getKey() + public function getLabel(): string { - return $this->config['key']; + return Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . $this->key; } /** - * Returns label name for option. - * - * @return string + * Returns translation key for option description. */ - public function getLabel() + public function getDescription(): string { - return Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . $this->name; + return Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . $this->key . '_description'; } - /** - * Returns translation key for option description. - * - * @return string - */ - public function getDescription() + public function getType(): string { - return Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . $this->name . '_description'; + if (isset($this->config['type'])) { + return $this->config['type']; + } + + return 'text'; } /** @@ -90,13 +85,27 @@ public function getDescription() */ public function getElementType() { - if (isset($this->config['type'])) { - $type = $this->config['type']; - } else { + $type = $this->getType(); + + if (null === $type) { $type = 'text'; } - return $type; + switch ($this->getType()) { + case 'int': + return 'number'; + case 'bool': + return 'checkbox'; + case 'string': + return 'text'; + default: + return $type; + } + } + + public function getElementId(): string + { + return str_replace('.', '_', $this->getKey()); } /** @@ -128,4 +137,17 @@ public function getOptions() return []; } } + + public function getValue(): string + { + $configuration = new Configuration(); + return $configuration->getOption($this->getKey()); + } + + public function setValue(?string $value): self + { + $configuration = new Configuration(); + $configuration->setOption($this->getKey(), $value); + return $this; + } } diff --git a/modules/admin/models/Options.php b/modules/admin/models/Options.php index 6d07df5de..c2a1f20f3 100644 --- a/modules/admin/models/Options.php +++ b/modules/admin/models/Options.php @@ -38,54 +38,41 @@ class Admin_Model_Options extends Application_Model_Abstract /** * Path to options configuration. */ - public const OPTIONS_CONFIG_FILE = '/modules/admin/models/options.json'; + public const OPTIONS_CONFIG_FILE = '/application/configs/options.yml'; /** @var array Option objects. */ private $options; - /** @var Zend_Config */ + /** @var array */ private $config; - /** - * @param Zend_Config|null $config - * - * TODO allow providing Zend_Config object - */ - public function __construct($config = null) + public function __construct(?array $config = null) { - if ($config !== null && is_array($config)) { - $this->config = new Zend_Config($config); - } + $this->config = $config; } /** * Returns options configuration from file. - * - * @return array */ - public function getOptions() + public function getOptions(): array { if ($this->options === null) { $this->options = []; - $config = $this->getConfig(); - $options = $config->toArray(); - foreach ($options as $name => $parameters) { - $this->options[$name] = new Admin_Model_Option($name, $parameters); + $config = $this->getConfig(); + + foreach ($config as $optionKey => $parameters) { + $this->options[$optionKey] = new Admin_Model_Option($optionKey, $parameters); } } return $this->options; } - /** - * @return Zend_Config - * @throws Zend_Config_Exception - */ - public function getConfig() + public function getConfig(): array { if ($this->config === null) { - $this->config = new Zend_Config_Json(APPLICATION_PATH . self::OPTIONS_CONFIG_FILE); + $this->config = yaml_parse_file(APPLICATION_PATH . self::OPTIONS_CONFIG_FILE); } return $this->config; diff --git a/modules/admin/models/options.json b/modules/admin/models/options.json deleted file mode 100644 index 24565c4a7..000000000 --- a/modules/admin/models/options.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "maxSearchResults": { - "key": "searchengine.solr.parameterDefaults.rows", - "type": "number", - "section": "searchopt", - "options": { - "min": 10, - "required": "true" - } - }, - "seriesSortByTitle": { - "key": "browsing.series.sortByTitle", - "type": "checkbox", - "section": "browsing" - } -} - - diff --git a/modules/default/language/fieldvalues.tmx b/modules/default/language/fieldvalues.tmx index 3b9c85651..47f4e9fc1 100644 --- a/modules/default/language/fieldvalues.tmx +++ b/modules/default/language/fieldvalues.tmx @@ -698,105 +698,6 @@ - - - - - - - - - - - - - - Individual - - - Individuell - - - - - - Macrolanguage - - - Macrosprache - - - - - - Special - - - Spezial - - - - - - - - - - - - - - - - - Ancient - - - Antik - - - - - - Constructed - - - Konstruiert - - - - - - Extinct - - - Ausgestorben - - - - - - Historical - - - Historisch - - - - - - Living - - - Lebend - - - - - - Special - - - Spezial - - - NULL diff --git a/modules/home/views/scripts/index/index.phtml b/modules/home/views/scripts/index/index.phtml index b19e045e4..5811d0105 100644 --- a/modules/home/views/scripts/index/index.phtml +++ b/modules/home/views/scripts/index/index.phtml @@ -31,13 +31,7 @@ ?> -headLink([ - 'rel' => 'alternate', - 'type' => 'application/rss+xml', - 'href' => $this->serverUrl() . $this->baseUrl() . '/rss/index/index', - ]); - ?> +rssMetaLink() ?> title = 'home_index_index_pagetitle' ?> diff --git a/modules/oai/models/DefaultServer.php b/modules/oai/models/DefaultServer.php index 501d71760..f9f03a2f0 100644 --- a/modules/oai/models/DefaultServer.php +++ b/modules/oai/models/DefaultServer.php @@ -335,7 +335,10 @@ protected function handleRequestIntern($oaiRequest, $requestUri) */ protected function setupProcessor() { - $this->proc->registerPHPFunctions('Opus\Common\Language::getLanguageCode'); + $this->proc->registerPHPFunctions([ + 'Opus\I18n\Languages::getPart1', + 'Opus\I18n\Languages::getPart2b', + ]); Application_Xslt::registerViewHelper($this->proc, $this->getViewHelpers()); $this->proc->setParameter('', 'urnResolverUrl', $this->getConfig()->urn->resolverUrl); $this->proc->setParameter('', 'doiResolverUrl', $this->getConfig()->doi->resolverUrl); diff --git a/modules/oai/views/scripts/index/prefixes/XMetaDissPlus.xslt b/modules/oai/views/scripts/index/prefixes/XMetaDissPlus.xslt index a85b7d963..dc146654e 100644 --- a/modules/oai/views/scripts/index/prefixes/XMetaDissPlus.xslt +++ b/modules/oai/views/scripts/index/prefixes/XMetaDissPlus.xslt @@ -152,7 +152,7 @@ - + @@ -254,7 +254,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -369,7 +369,7 @@ - + diff --git a/modules/oai/views/scripts/index/prefixes/oai_dc.xslt b/modules/oai/views/scripts/index/prefixes/oai_dc.xslt index b47c5d058..7a2d4a415 100644 --- a/modules/oai/views/scripts/index/prefixes/oai_dc.xslt +++ b/modules/oai/views/scripts/index/prefixes/oai_dc.xslt @@ -138,7 +138,7 @@ - + @@ -202,7 +202,7 @@ - + @@ -218,7 +218,7 @@ - + @@ -362,7 +362,7 @@ - + diff --git a/modules/publish/models/Validation.php b/modules/publish/models/Validation.php index 94e9b66a7..e1f493a86 100644 --- a/modules/publish/models/Validation.php +++ b/modules/publish/models/Validation.php @@ -431,7 +431,6 @@ private function languageSelect() { $languages = $this->getLanguages(); if (isset($languages) || count($languages) >= 1) { - asort($languages); return $languages; } return null; diff --git a/modules/setup/controllers/LanguageController.php b/modules/setup/controllers/LanguageController.php index 537f2adca..7409d9fa5 100644 --- a/modules/setup/controllers/LanguageController.php +++ b/modules/setup/controllers/LanguageController.php @@ -29,8 +29,6 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ -use Opus\App\Common\Configuration; - /** * TODO rename controller to TranslationController * TODO sorting using table header @@ -494,8 +492,7 @@ public function settingsAction() // TODO provide form with options config $form = new Admin_Form_Configuration([ - 'supportedLanguages' => [ - 'key' => 'activatedLanguages', + 'activatedLanguages' => [ 'type' => 'supportedLanguages', 'section' => 'general', ], @@ -513,7 +510,6 @@ public function settingsAction() if ($form->isValid($data)) { $config = new Zend_Config([], true); $form->updateModel($config); - Configuration::save($config); } else { break; } @@ -529,7 +525,7 @@ public function settingsAction() $form->populateFromModel($config); - $element = $form->getElement('supportedLanguages'); + $element = $form->getElement('activatedLanguages'); if (! isset($config->activatedLanguages)) { $element->setValue($config->supportedLanguages); } diff --git a/modules/solrsearch/views/scripts/browse/doctypes.phtml b/modules/solrsearch/views/scripts/browse/doctypes.phtml index 814c9fef7..cb93e7f0f 100644 --- a/modules/solrsearch/views/scripts/browse/doctypes.phtml +++ b/modules/solrsearch/views/scripts/browse/doctypes.phtml @@ -41,9 +41,7 @@
  • translate($facetitem->getText())) ?>  (getCount() ?>) - - <?= $this->translate('rss_icon') ?> - + rssLink(['searchtype' => 'simple', 'query' => '*:*', 'doctypefq' => $facetitem->getText()]) ?>
  • diff --git a/modules/solrsearch/views/scripts/browse/index.phtml b/modules/solrsearch/views/scripts/browse/index.phtml index eb469f268..d995cf034 100644 --- a/modules/solrsearch/views/scripts/browse/index.phtml +++ b/modules/solrsearch/views/scripts/browse/index.phtml @@ -44,9 +44,7 @@ showLatestDocuments) : ?>
  • translate('latest_documents_title')) ?>  - - <?= $this->translate('rss_icon') ?> - + rssLink() ?>
  • showDocumentTypes) : ?> diff --git a/modules/solrsearch/views/scripts/browse/series.phtml b/modules/solrsearch/views/scripts/browse/series.phtml index eef51c2bc..5fe693067 100644 --- a/modules/solrsearch/views/scripts/browse/series.phtml +++ b/modules/solrsearch/views/scripts/browse/series.phtml @@ -38,9 +38,7 @@ series as $seriesitem) : ?>
  • - - <?= $this->translate('rss_icon') ?> - + rssLink(['searchtype' => 'series', 'id' => $seriesitem['id']]) ?>
  • diff --git a/modules/solrsearch/views/scripts/browse/years.phtml b/modules/solrsearch/views/scripts/browse/years.phtml index 1baa05f8a..41c59af95 100644 --- a/modules/solrsearch/views/scripts/browse/years.phtml +++ b/modules/solrsearch/views/scripts/browse/years.phtml @@ -41,10 +41,7 @@
  • translate($facetitem->getText())) ?>  (getCount() ?>) - - <?= $this->translate('rss_icon') ?> - + rssLink(['searchtype' => 'simple', 'query' => '*:*', 'yearfq' => $facetitem->getText()]) ?>
  • diff --git a/modules/solrsearch/views/scripts/index/browsecollection.phtml b/modules/solrsearch/views/scripts/index/browsecollection.phtml index eaf5e031b..5e28286f6 100644 --- a/modules/solrsearch/views/scripts/index/browsecollection.phtml +++ b/modules/solrsearch/views/scripts/index/browsecollection.phtml @@ -84,10 +84,7 @@ use Opus\Common\Config; getDisplayNameForBrowsingContext($this->collectionRole)) ?> () - - <?= $this->translate('rss_icon') ?> - + rssLink(['searchtype' => 'collection', 'id' => $child->getId()]) ?> diff --git a/modules/solrsearch/views/scripts/index/nohits.phtml b/modules/solrsearch/views/scripts/index/nohits.phtml index 1e65c61bb..fb0834ffd 100644 --- a/modules/solrsearch/views/scripts/index/nohits.phtml +++ b/modules/solrsearch/views/scripts/index/nohits.phtml @@ -31,13 +31,7 @@ ?> -headLink([ - 'rel' => 'alternate', - 'type' => 'application/rss+xml', - 'href' => $this->serverUrl() . $this->url($this->rssUrl), - ]); - ?> +rssMetaLink($this->url($this->rssUrl)) ?> searchType === 'simple') { diff --git a/modules/solrsearch/views/scripts/index/results.phtml b/modules/solrsearch/views/scripts/index/results.phtml index 7b7a55243..863087a6a 100644 --- a/modules/solrsearch/views/scripts/index/results.phtml +++ b/modules/solrsearch/views/scripts/index/results.phtml @@ -37,13 +37,7 @@ if ($this->jQueryEnabled()) { } ?> -headLink([ - 'rel' => 'alternate', - 'type' => 'application/rss+xml', - 'href' => $this->serverUrl() . $this->url($this->rssUrl), - ]); - ?> +rssMetaLink($this->url($this->rssUrl)) ?> specialTitle)) : ?>

    specialTitle) ?>

    diff --git a/modules/solrsearch/views/scripts/index/simpleSearchForm.phtml b/modules/solrsearch/views/scripts/index/simpleSearchForm.phtml index aae0f5a09..636a3b449 100644 --- a/modules/solrsearch/views/scripts/index/simpleSearchForm.phtml +++ b/modules/solrsearch/views/scripts/index/simpleSearchForm.phtml @@ -60,9 +60,7 @@ if ($this->jQueryEnabled()) { ?> translate('solrsearch_title_latest'); ?> - - <?= $this->translate('rss_icon') ?> - + rssLink() ?>

    diff --git a/public/index.php b/public/index.php index 9d0bc9982..250fdf0cf 100644 --- a/public/index.php +++ b/public/index.php @@ -71,14 +71,6 @@ $config->merge($localConfig); -// configuration file that is modified via application user interface -if (is_readable(APPLICATION_PATH . '/application/configs/config.xml')) { - $onlineConfig = new Zend_Config_Xml( - APPLICATION_PATH . '/application/configs/config.xml' - ); - $config->merge($onlineConfig); -} - // Create application, bootstrap, and run $application = new Zend_Application(APPLICATION_ENV, $config); diff --git a/scripts/change-password.php b/scripts/change-password.php deleted file mode 100644 index 2a717dd1e..000000000 --- a/scripts/change-password.php +++ /dev/null @@ -1,49 +0,0 @@ -setPassword($password)->store(); diff --git a/tests/library/Application/Form/Element/LanguageTypeTest.php b/scripts/update/021-Move-config-xml-to-db.php old mode 100644 new mode 100755 similarity index 52% rename from tests/library/Application/Form/Element/LanguageTypeTest.php rename to scripts/update/021-Move-config-xml-to-db.php index b71d49e30..6fd9cbf53 --- a/tests/library/Application/Form/Element/LanguageTypeTest.php +++ b/scripts/update/021-Move-config-xml-to-db.php @@ -25,55 +25,52 @@ * along with OPUS; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * @copyright Copyright (c) 2008, OPUS 4 development team + * @copyright Copyright (c) 2026, OPUS 4 development team * @license http://www.gnu.org/licenses/gpl.html General Public License */ -class Application_Form_Element_LanguageTypeTest extends FormElementTestCase -{ - /** @var string */ - protected $additionalResources = 'translation'; +require_once dirname(__FILE__) . '/../common/update.php'; - /** @var string[] */ - private $keys; +use Opus\Db2\Configuration; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Filesystem\Filesystem; - public function setUp(): void - { - $this->keys = ['Null', 'A', 'C', 'E', 'H', 'L', 'S']; - $this->formElementClass = 'Application_Form_Element_LanguageType'; - $this->expectedDecorators = [ - 'ViewHelper', - 'Errors', - 'Description', - 'ElementHtmlTag', - 'LabelNotEmpty', - 'dataWrapper', - 'ElementHint', - ]; - $this->expectedDecoratorCount = count($this->expectedDecorators); - $this->staticViewHelper = 'viewFormSelect'; - parent::setUp(); - } +$output = new ConsoleOutput(); - public function testOptions() - { - $element = $this->getElement(); +$configPath = APPLICATION_PATH . '/application/configs/config.xml'; - $options = $element->getMultiOptions(); +if (! file_exists($configPath)) { + exit(); +} - $this->assertEquals(count($this->keys), count($options)); +$output->writeln("Importing '{$configPath}' into database."); - foreach ($this->keys as $key) { - $this->assertTrue(array_key_exists($key, $options), "Key '$key' is missing."); - } - } +if (! is_readable($configPath)) { + $output->writeln('File \'' . $configPath . '\' is not readable.'); + exit(); +} - public function testOptionsTranslated() - { - $translator = Application_Translate::getInstance(); +// Import options from config.xml +$config = new Zend_Config_Xml($configPath); +$configDatabase = new Configuration(); +$configDatabase->import($config, false); // No reset because `MigrateLanguages` schema update creates options - foreach ($this->keys as $key) { - $this->assertTrue($translator->isTranslated('Opus_Language_Type_Value_' . $key)); - } +// Show imported options +$imported = $configDatabase->getConfig(); +if (count($imported) > 0) { + $options = $configDatabase->arr2ini($imported->toArray()); + $output->writeln('Imported options:'); + foreach ($options as $key => $value) { + $output->writeln(' ' . $key . ' = ' . $value); } } + +// Remove config.xml file +$helper = new Application_Update_Helper(); + +if ($helper->askYesNo("Delete '{$configPath}' file [Y/n]?", true)) { + $output->write("Removeing '{$configPath}' file ... "); + $filesystem = new Filesystem(); + $filesystem->remove($configPath); + $output->writeln('done'); +} diff --git a/library/Application/Form/Element/LanguageScope.php b/scripts/update/022-Remove-resource_languages.php old mode 100644 new mode 100755 similarity index 78% rename from library/Application/Form/Element/LanguageScope.php rename to scripts/update/022-Remove-resource_languages.php index faae0a3f3..44a261f6f --- a/library/Application/Form/Element/LanguageScope.php +++ b/scripts/update/022-Remove-resource_languages.php @@ -25,20 +25,21 @@ * along with OPUS; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * @copyright Copyright (c) 2008, OPUS 4 development team + * @copyright Copyright (c) 2026, OPUS 4 development team * @license http://www.gnu.org/licenses/gpl.html General Public License */ -class Application_Form_Element_LanguageScope extends Application_Form_Element_SelectWithNull -{ - public function init() - { - parent::init(); +require_once dirname(__FILE__) . '/../common/update.php'; - $values = ['Null', 'I', 'M', 'S']; +use Opus\SecurityStorage; +use Symfony\Component\Console\Output\ConsoleOutput; - foreach ($values as $value) { - $this->addMultiOption($value, 'Opus_Language_Scope_Value_' . $value); - } - } -} +$output = new ConsoleOutput(); + +$output->writeln(''); +$output->write('Removing \'resource_languages\' from role permissions...'); + +$security = new SecurityStorage(); +$security->removeResource('resource_languages'); + +$output->writeln(' done'); diff --git a/tests/library/Application/Controller/Action/Helper/TranslationTest.php b/tests/library/Application/Controller/Action/Helper/TranslationTest.php index b5e890a27..befa9ffdd 100644 --- a/tests/library/Application/Controller/Action/Helper/TranslationTest.php +++ b/tests/library/Application/Controller/Action/Helper/TranslationTest.php @@ -30,7 +30,6 @@ */ use Opus\Common\Identifier; -use Opus\Common\Language; use Opus\Common\Model\ModelException; use Opus\Common\Note; use Opus\Common\Person; @@ -281,14 +280,4 @@ public function testTranslationOfOpusEnrichmentFields($className) ); } } - - public function testTranslationOfLanguages() - { - $languages = Language::getAll(); - - foreach ($languages as $language) { - $key = $language->getPart2T(); - $this->assertNotEquals($key, $this->translate->translateLanguage($key)); - } - } } diff --git a/tests/library/Application/Form/Element/LanguageTest.php b/tests/library/Application/Form/Element/LanguageTest.php index 31a4b9f4f..07a002e93 100644 --- a/tests/library/Application/Form/Element/LanguageTest.php +++ b/tests/library/Application/Form/Element/LanguageTest.php @@ -95,8 +95,20 @@ public function testValidation() $this->assertTrue($element->isValid('deu')); } + public function testAutoMapValueToLanguageId() + { + $element = $this->getElement(); + $element->setValue('ger'); + $this->assertEquals('deu', $element->getValue()); + } + public function testUnknownLanguage() { - $this->markTestIncomplete(); + $language = $this->getElement(); + $langCode = 'cmn'; + + $language->setValue($langCode); + $this->assertEquals($langCode, $language->getValue()); + $this->assertTrue($language->isValid($langCode)); } } diff --git a/tests/library/Application/Security/AccessTest.php b/tests/library/Application/Security/AccessTest.php index 4c2a385ab..842c09b54 100644 --- a/tests/library/Application/Security/AccessTest.php +++ b/tests/library/Application/Security/AccessTest.php @@ -57,7 +57,6 @@ public function testLicenceAdminMenuFiltering() $this->assertNotQuery('//a[@href="/review"]'); $this->assertNotQuery('//a[@href="/admin/collectionroles"]'); $this->assertNotQuery('//a[@href="/admin/series"]'); - $this->assertNotQuery('//a[@href="/admin/language"]'); $this->assertNotQuery('//a[@href="/admin/index/security"]'); $this->assertNotQuery('//a[@href="/admin/dnbinstitute"]'); } diff --git a/tests/library/Application/View/Helper/RssLinkTest.php b/tests/library/Application/View/Helper/RssLinkTest.php new file mode 100644 index 000000000..c0636141c --- /dev/null +++ b/tests/library/Application/View/Helper/RssLinkTest.php @@ -0,0 +1,118 @@ +helper = new Application_View_Helper_RssLink(); + $this->helper->setView($this->getView()); + } + + public function testRssLinkDefault() + { + $output = $this->helper->rssLink(); + + $expected = << + rss_icon + +EOT; + + $this->assertEquals($expected, $output); + } + + public function testRssLinkWithArray() + { + $output = $this->helper->rssLink(['searchtype' => 'collection', 'id' => 147]); + + $expected = << + rss_icon + +EOT; + + $this->assertEquals($expected, $output); + } + + public function testRssLinkWithString() + { + $output = $this->helper->rssLink('/rss/index/index/searchtype/latest'); + + $expected = << + rss_icon + +EOT; + + $this->assertEquals($expected, $output); + } + + public function testRssLinkDisabled() + { + $this->adjustConfiguration([ + 'rss' => ['showLinks' => false], + ]); + + $output = $this->helper->rssLink(); + + $this->assertEquals('', $output); + } + + public function testRssLinkNoAccess() + { + $this->enableSecurity(); + + $guest = UserRole::fetchByName('guest'); + $guest->removeAccessModule('rss'); + $guest->store(); + + $output = $this->helper->rssLink(); + + $guest->appendAccessModule('rss'); + $guest->store(); + + $this->assertEquals('', $output); + } +} diff --git a/tests/library/Application/Form/Element/LanguageScopeTest.php b/tests/library/Application/View/Helper/RssMetaLinkTest.php similarity index 54% rename from tests/library/Application/Form/Element/LanguageScopeTest.php rename to tests/library/Application/View/Helper/RssMetaLinkTest.php index 0b495cacb..d33e8472f 100644 --- a/tests/library/Application/Form/Element/LanguageScopeTest.php +++ b/tests/library/Application/View/Helper/RssMetaLinkTest.php @@ -25,59 +25,71 @@ * along with OPUS; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * @copyright Copyright (c) 2008, OPUS 4 development team + * @copyright Copyright (c) 2026, OPUS 4 development team * @license http://www.gnu.org/licenses/gpl.html General Public License */ -class Application_Form_Element_LanguageScopeTest extends FormElementTestCase -{ - /** @var string */ - protected $additionalResources = 'translation'; +use Opus\Common\UserRole; +/** + * @covers Application_View_Helper_RssMetaLink + */ +class Application_View_Helper_RssMetaLinkTest extends ControllerTestCase +{ /** @var string[] */ - private $keys; + protected $additionalResources = ['view', 'database']; + + /** @var Application_View_Helper_RssMetaLink */ + private $helper; public function setUp(): void { - $this->keys = ['Null', 'I', 'M', 'S']; - - $this->formElementClass = 'Application_Form_Element_LanguageScope'; - $this->expectedDecorators = [ - 'ViewHelper', - 'Errors', - 'Description', - 'ElementHtmlTag', - 'LabelNotEmpty', - 'dataWrapper', - 'ElementHint', - ]; - $this->expectedDecoratorCount = count($this->expectedDecorators); - $this->staticViewHelper = 'viewFormSelect'; parent::setUp(); + + $this->helper = new Application_View_Helper_RssMetaLink(); + $this->helper->setView($this->getView()); } - public function testOptions() + public function testRssMetaLink() { - $element = $this->getElement(); + $output = $this->helper->rssMetaLink(); + + $this->assertEquals('', $output); + + $view = $this->getView(); - $options = $element->getMultiOptions(); + $links = $view->headLink()->toString(); - $this->assertEquals(count($this->keys), count($options)); + $this->assertEquals( + '', + $links + ); + } + + public function testRssMetaLinkDisabled() + { + $this->adjustConfiguration([ + 'rss' => ['showLinks' => false], + ]); + + $this->helper->rssMetaLink(); - foreach ($this->keys as $key) { - $this->assertTrue(array_key_exists($key, $options), "Key '$key' is missing."); - } + $this->assertEquals('', $this->getView()->headLink()->toString()); } - public function testOptionsTranslated() + public function testRssMetaLinkNoAccess() { - $translator = Application_Translate::getInstance(); - - foreach ($this->keys as $key) { - $this->assertTrue( - $translator->isTranslated('Opus_Language_Scope_Value_' . $key), - "Key '$key' not translated." - ); - } + $this->enableSecurity(); + + $guest = UserRole::fetchByName('guest'); + $guest->removeAccessModule('rss'); + $guest->store(); + + $this->helper->rssMetaLink(); + + $guest->appendAccessModule('rss'); + $guest->store(); + + $this->assertEquals('', $this->getView()->headLink()->toString()); } } diff --git a/tests/modules/MainMenuTest.php b/tests/modules/MainMenuTest.php index 3077d9049..668676270 100644 --- a/tests/modules/MainMenuTest.php +++ b/tests/modules/MainMenuTest.php @@ -78,7 +78,6 @@ public function testAdminControllerIndexPages() "/admin/collectionroles", "/admin/series", "/admin/security", - "/admin/language", "/admin/statistic", "/admin/oailink", "/admin/dnbinstitute", diff --git a/tests/modules/admin/controllers/DnbinstituteControllerTest.php b/tests/modules/admin/controllers/DnbinstituteControllerTest.php index beb251f73..bfe098340 100644 --- a/tests/modules/admin/controllers/DnbinstituteControllerTest.php +++ b/tests/modules/admin/controllers/DnbinstituteControllerTest.php @@ -342,7 +342,7 @@ public function testUserAccessToInstituteWithoutInstituteRights() $testRole = UserRole::new(); $testRole->setName('TestRole'); $testRole->appendAccessModule('admin'); - $testRole->appendAccessModule('resource_languages'); + $testRole->appendAccessModule('resource_collections'); $this->roleId = $testRole->store(); $userAccount = Account::new(); diff --git a/tests/modules/admin/controllers/LanguageControllerTest.php b/tests/modules/admin/controllers/LanguageControllerTest.php deleted file mode 100644 index ddd306b9d..000000000 --- a/tests/modules/admin/controllers/LanguageControllerTest.php +++ /dev/null @@ -1,295 +0,0 @@ -setController('language'); - parent::setUp(); - } - - /** - * @return LanguageInterface[] - */ - public function getModels() - { - return Language::getAll(); - } - - public function testShowAction() - { - $this->createsModels = true; - - $language = Language::new(); - - $language->setActive(true); - $language->setRefName('German'); - $language->setPart2T('deu'); - $language->setPart2B('ger'); - $language->setPart1('de'); - $language->setScope('I'); - $language->setType('L'); - $language->setComment('test comment'); - - $modelId = $language->store(); - - $this->dispatch('/admin/language/show/id/' . $modelId); - - $model = Language::get($modelId); - $model->delete(); - - $this->assertResponseCode(200); - $this->assertController('language'); - $this->assertAction('show'); - - $this->assertQueryContentRegex('div#Active', '/Yes|Ja/'); - $this->assertQueryContentContains('div#RefName', 'German'); - $this->assertQueryContentContains('div#Part2T', 'deu'); - $this->assertQueryContentContains('div#Part2B', 'ger'); - $this->assertQueryContentContains('div#Part1', 'de'); - $this->assertQueryContentRegex('div#Scope', '/Individual|Individuell/'); - $this->assertQueryContentRegex('div#Type', '/Living|Lebend/'); - $this->assertQueryContentContains('div#Comment', 'test comment'); - - // TODO $this->validateXHTML(); - } - - /** - * Test, ob Active Status für Wert false (0) angezeigt wird. - */ - public function testShowActiveValueForInactiveLicence() - { - $this->dispatch('/admin/language/show/id/3'); // Italian (3) is disabled - $this->assertResponseCode(200); - $this->assertController('language'); - $this->assertAction('show'); - - $this->assertQueryContentRegex('div#Active', '/No|Nein/'); - } - - public function testNewActionSave() - { - $this->createsModels = true; - - $post = [ - 'Active' => '1', - 'RefName' => 'German', - 'Part2T' => 'deu', - 'Part2B' => 'ger', - 'Part1' => 'de', - 'Scope' => 'I', - 'Type' => 'L', - 'Comment' => 'test comment', - 'Save' => 'Speichern', - ]; - - $this->getRequest()->setPost($post)->setMethod('POST'); - - $this->dispatch('/admin/language/new'); - - $this->assertRedirect('Should be a redirect to show action.'); - $this->assertRedirectRegex('/^\/admin\/language\/show/'); // Regex weil danach noch '/id/xxx' kommt - $this->verifyFlashMessage('controller_crud_save_success', self::MESSAGE_LEVEL_NOTICE); - - // Neue Lizenz anzeigen - $location = $this->getLocation(); - - $this->resetRequest(); - $this->resetResponse(); - - $this->dispatch($location); - $this->assertResponseCode(200); - - $this->assertQueryContentRegex('div#Active', '/Yes|Ja/'); - $this->assertQueryContentContains('div#RefName', 'German'); - $this->assertQueryContentContains('div#Part2T', 'deu'); - $this->assertQueryContentContains('div#Part2B', 'ger'); - $this->assertQueryContentContains('div#Part1', 'de'); - $this->assertQueryContentRegex('div#Scope', '/Individual|Individuell/'); - $this->assertQueryContentRegex('div#Type', '/Living|Lebend/'); - $this->assertQueryContentContains('div#Comment', 'test comment'); - } - - public function testNewActionCancel() - { - $this->createsModels = true; - - $modelCount = count($this->getModels()); - - $post = [ - 'RefName' => 'TestGerman', - 'Part2T' => 'tge', - 'Cancel' => 'Abbrechen', - ]; - - $this->getRequest()->setPost($post)->setMethod('POST'); - - $this->dispatch('/admin/language/new'); - - $this->assertRedirectTo('/admin/language', 'Should be a redirect to index action.'); - - $this->assertEquals( - $modelCount, - count(Language::getAll()), - 'Es sollte keine neue Sprache geben.' - ); - } - - /** - * Tests 'edit' action. - */ - public function testEditActionShowForm() - { - $this->dispatch('/admin/language/edit/id/3'); - $this->assertResponseCode(200); - $this->assertController('language'); - $this->assertAction('edit'); - - $this->assertQueryContentContains('div#RefName-element', 'Italian'); - $this->assertQuery('li.save-element'); - $this->assertQuery('li.cancel-element'); - $this->assertQueryCount('input#Id', 1); - } - - public function testEditActionSave() - { - $this->createsModels = true; - - $model = Language::new(); - - $model->setRefName('Test'); - $model->setPart2T('tst'); - - $modelId = $model->store(); - - $this->getRequest()->setMethod('POST')->setPost([ - 'Id' => $modelId, - 'Active' => '1', - 'RefName' => 'RefNameModified', - 'Part2T' => 'n2t', - 'Part2B' => 'tet', - 'Part1' => 'us', - 'Scope' => 'I', - 'Type' => 'L', - 'Comment' => 'test comment', - 'Save' => 'Speichern', - ]); - - $this->dispatch('/admin/language/edit'); - $this->assertRedirectTo('/admin/language/show/id/' . $modelId); - $this->verifyFlashMessage('controller_crud_save_success', self::MESSAGE_LEVEL_NOTICE); - - $model = Language::get($modelId); - - $this->assertEquals(1, $model->getActive()); - $this->assertEquals('RefNameModified', $model->getRefName()); - $this->assertEquals('n2t', $model->getPart2T()); - $this->assertEquals('tet', $model->getPart2B()); - $this->assertEquals('us', $model->getPart1()); - $this->assertEquals('I', $model->getScope()); - $this->assertEquals('L', $model->getType()); - $this->assertEquals('test comment', $model->getComment()); - } - - public function testEditActionCancel() - { - $this->createsModels = true; - - $model = Language::new(); - - $model->setRefName('Test'); - $model->setPart2T('tst'); - - $modelId = $model->store(); - - $this->getRequest()->setMethod('POST')->setPost([ - 'Id' => $modelId, - 'RefName' => 'RefNameModified', - 'Part2T' => 'tes', - 'Cancel' => 'Abbrechen', - ]); - - $this->dispatch('/admin/language/edit'); - $this->assertRedirectTo('/admin/language'); - - $model = Language::get($modelId); - - $this->assertEquals('Test', $model->getRefName()); - } - - public function testDeleteActionShowForm() - { - $this->useEnglish(); - - $this->dispatch('/admin/language/delete/id/3'); - - $this->assertQueryContentContains('legend', 'Delete Language'); - $this->assertQueryContentContains('span.displayname', 'Italian'); - $this->assertQuery('input#ConfirmYes'); - $this->assertQuery('input#ConfirmNo'); - } - - /** - * @return int - */ - public function createNewModel() - { - $model = Language::new(); - - $model->setRefName('TestLang'); - $model->setPart2T('lan'); - - return $model->store(); - } - - /** - * @param int $identifier - * @return LanguageInterface - * @throws NotFoundException - */ - public function getModel($identifier) - { - return Language::get($identifier); - } -} diff --git a/tests/modules/admin/forms/ConfigurationTest.php b/tests/modules/admin/forms/ConfigurationTest.php index 3a3a844ed..1a24799e8 100644 --- a/tests/modules/admin/forms/ConfigurationTest.php +++ b/tests/modules/admin/forms/ConfigurationTest.php @@ -29,6 +29,8 @@ * @license http://www.gnu.org/licenses/gpl.html General Public License */ +use Opus\Db2\Configuration; + class Admin_Form_ConfigurationTest extends ControllerTestCase { /** @var string[] */ @@ -51,7 +53,7 @@ public function testPopulateFromModel() 'searchengine' => ['solr' => ['parameterDefaults' => ['rows' => '20']]], ])); // searchengine.solr.parameterDefaults.rows - $element = $form->getElement('maxSearchResults'); + $element = $form->getElement('searchengine_solr_parameterDefaults_rows'); $this->assertNotNull($element); $this->assertEquals(20, $element->getValue()); @@ -61,13 +63,16 @@ public function testUpdateModel() { $form = new Admin_Form_Configuration(); - $form->getElement('maxSearchResults')->setValue(15); + $form->getElement('searchengine_solr_parameterDefaults_rows')->setValue(15); $config = new Zend_Config([], true); $form->updateModel($config); - $this->assertEquals(15, $config->searchengine->solr->parameterDefaults->rows); + $configDatabase = new Configuration(); + $this->assertEquals(15, $configDatabase->getOption( + 'searchengine.solr.parameterDefaults.rows' + )); } public function testValidationSuccess() @@ -75,8 +80,7 @@ public function testValidationSuccess() $form = new Admin_Form_Configuration(); $this->assertTrue($form->isValid([ - 'supportedLanguages' => ['de'], - 'maxSearchResults' => '10', + 'searchengine_solr_parameterDefaults_rows' => '10', ])); } @@ -85,7 +89,16 @@ public function testValidationFailure() $form = new Admin_Form_Configuration(); $this->assertFalse($form->isValid([ - 'supportedLanguages' => ['ru'], + 'searchengine_solr_parameterDefaults_rows' => '5', ])); } + + public function testLoadOptionsConfig() + { + $optionsConfigPath = APPLICATION_PATH . '/application/configs/options.yml'; + + $options = yaml_parse_file($optionsConfigPath); + + $this->assertIsArray($options); + } } diff --git a/tests/modules/admin/forms/LanguageTest.php b/tests/modules/admin/forms/LanguageTest.php deleted file mode 100644 index 20094f569..000000000 --- a/tests/modules/admin/forms/LanguageTest.php +++ /dev/null @@ -1,175 +0,0 @@ -assertEquals(11, count($form->getElements())); - - $this->assertNotNull($form->getElement('Active')); - $this->assertNotNull($form->getElement('Part2B')); - $this->assertNotNull($form->getElement('Part2T')); - $this->assertNotNull($form->getElement('Part1')); - $this->assertNotNull($form->getElement('RefName')); - $this->assertNotNull($form->getElement('Comment')); - $this->assertNotNull($form->getElement('Scope')); - $this->assertNotNull($form->getElement('Type')); - - $this->assertNotNull($form->getElement('Save')); - $this->assertNotNull($form->getElement('Cancel')); - $this->assertNotNull($form->getElement('Id')); - } - - public function testPopulateFromModel() - { - $form = new Admin_Form_Language(); - - $language = Language::new(); - $language->setActive(true); - $language->setPart2B('ger'); - $language->setPart2T('deu'); - $language->setRefName('German'); - $language->setPart1('de'); - $language->setScope('M'); - $language->setType('H'); - $language->setComment('test comment'); - - $form->populateFromModel($language); - - $this->assertEquals(1, $form->getElement('Active')->getValue()); - $this->assertEquals('ger', $form->getElement('Part2B')->getValue()); - $this->assertEquals('deu', $form->getElement('Part2T')->getValue()); - $this->assertEquals('de', $form->getElement('Part1')->getValue()); - $this->assertEquals('German', $form->getElement('RefName')->getValue()); - $this->assertEquals('test comment', $form->getElement('Comment')->getValue()); - $this->assertEquals('M', $form->getElement('Scope')->getValue()); - $this->assertEquals('H', $form->getElement('Type')->getValue()); - $this->assertNull($form->getElement('Id')->getValue()); - } - - public function testPopulateFromModelWithId() - { - $form = new Admin_Form_Language(); - - $language = Language::get(2); - - $form->populateFromModel($language); - - $this->assertEquals(2, $form->getElement('Id')->getValue()); - } - - public function testUpdateModel() - { - $form = new Admin_Form_Language(); - - $form->getElement('Id')->setValue(99); - $form->getElement('Active')->setChecked(true); - $form->getElement('RefName')->setValue('German'); - $form->getElement('Part2B')->setValue('ger'); - $form->getElement('Part2T')->setValue('deu'); - $form->getElement('Part1')->setValue('de'); - $form->getElement('Comment')->setValue('Deutsch'); - $form->getElement('Scope')->setValue('I'); - $form->getElement('Type')->setValue('L'); - - $language = Language::new(); - - $form->updateModel($language); - - $this->assertNull($language->getId()); - $this->assertEquals(1, $language->getActive()); - $this->assertEquals('German', $language->getRefName()); - $this->assertEquals('ger', $language->getPart2B()); - $this->assertEquals('deu', $language->getPart2T()); - $this->assertEquals('de', $language->getPart1()); - $this->assertEquals('Deutsch', $language->getComment()); - $this->assertEquals('I', $language->getScope()); - $this->assertEquals('L', $language->getType()); - } - - public function testValidationEmptyPost() - { - $form = new Admin_Form_Language(); - - $this->assertFalse($form->isValid([])); - - $this->assertContains('isEmpty', $form->getErrors('RefName')); - $this->assertContains('isEmpty', $form->getErrors('Part2T')); - } - - public function testValidationEmptyFields() - { - $form = new Admin_Form_Language(); - - $this->assertFalse($form->isValid([ - 'RefName' => ' ', - 'Part2T' => ' ', - ])); - - $this->assertContains('isEmpty', $form->getErrors('RefName')); - $this->assertContains('isEmpty', $form->getErrors('Part2T')); - } - - public function testValidationInvalidValues() - { - $form = new Admin_Form_Language(); - - $this->assertFalse($form->isValid([ - 'RefName' => 'German', - 'Part2T' => 'deu', - 'Scope' => 'X', - 'Type' => 'Y', - ])); - - $this->assertNotContains('isEmpty', $form->getErrors('RefName')); - $this->assertNotContains('isEmpty', $form->getErrors('Part2T')); - $this->assertContains('notInArray', $form->getErrors('Scope')); - $this->assertContains('notInArray', $form->getErrors('Type')); - } - - public function testValidationTrue() - { - $form = new Admin_Form_Language(); - - $this->assertTrue($form->isValid([ - 'RefName' => 'German', - 'Part2T' => 'deu', - ])); - } -} diff --git a/tests/modules/admin/models/OptionTest.php b/tests/modules/admin/models/OptionTest.php index da7ec993d..03ad499ad 100644 --- a/tests/modules/admin/models/OptionTest.php +++ b/tests/modules/admin/models/OptionTest.php @@ -38,8 +38,7 @@ public function setUp(): void { parent::setUp(); - $this->model = new Admin_Model_Option('test', [ - 'key' => 'supportedLanguages', + $this->model = new Admin_Model_Option('supportedLanguages', [ 'type' => 'number', 'section' => 'search', 'options' => [ @@ -86,20 +85,23 @@ public function testGetDefaultElementType() public function testGetLabel() { - $this->assertEquals(Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . 'test', $this->model->getLabel()); + $this->assertEquals( + Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . 'supportedLanguages', + $this->model->getLabel() + ); } public function testGetDescription() { $this->assertEquals( - Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . 'test_description', + Admin_Form_Configuration::LABEL_TRANSLATION_PREFIX . 'supportedLanguages_description', $this->model->getDescription() ); } public function testGetName() { - $this->assertEquals('test', $this->model->getName()); + $this->assertEquals('supportedLanguages', $this->model->getKey()); } public function testGetKey() diff --git a/tests/modules/admin/models/OptionsTest.php b/tests/modules/admin/models/OptionsTest.php index e74f4c855..d992c8a6a 100644 --- a/tests/modules/admin/models/OptionsTest.php +++ b/tests/modules/admin/models/OptionsTest.php @@ -46,11 +46,11 @@ public function testGetOptions() $options = $this->model->getOptions(); $this->assertIsArray($options); - $this->assertCount(2, $options); + $this->assertCount(4, $options); foreach ($options as $name => $option) { $this->assertInstanceOf(Admin_Model_Option::class, $option); - $this->assertEquals($name, $option->getName()); + $this->assertEquals($name, $option->getKey()); } } } diff --git a/tests/security/AdministratorRoleTest.php b/tests/security/AdministratorRoleTest.php index 41e6e3c90..9023202bb 100644 --- a/tests/security/AdministratorRoleTest.php +++ b/tests/security/AdministratorRoleTest.php @@ -62,7 +62,6 @@ public function testAdministratorRoleHasSuperPrivileges() $this->assertQuery('//a[@href="/admin/index/security"]'); $this->assertQuery('//a[@href="/admin/collectionroles"]'); $this->assertQuery('//a[@href="/admin/series"]'); - $this->assertQuery('//a[@href="/admin/language"]'); $this->assertQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertQuery('//a[@href="/admin/index/info"]'); $this->assertQuery('//a[@href="/review"]'); diff --git a/tests/security/CollectionsAdminTest.php b/tests/security/CollectionsAdminTest.php index d2b9cf387..17dd48133 100644 --- a/tests/security/CollectionsAdminTest.php +++ b/tests/security/CollectionsAdminTest.php @@ -63,7 +63,6 @@ public function testAdminMenuFiltering() $this->assertNotQuery('//a[@href="/admin/index/security"]'); $this->assertQuery('//a[@href="/admin/collectionroles"]'); $this->assertNotQuery('//a[@href="/admin/series"]'); - $this->assertNotQuery('//a[@href="/admin/language"]'); $this->assertNotQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertNotQuery('//a[@href="/review"]'); $this->assertNotQuery('//a[@href="/admin/index/setup"]'); diff --git a/tests/security/DocumentsAdminTest.php b/tests/security/DocumentsAdminTest.php index a920ce4e6..dc5473f39 100644 --- a/tests/security/DocumentsAdminTest.php +++ b/tests/security/DocumentsAdminTest.php @@ -64,7 +64,6 @@ public function testAdminMenuFiltering() $this->assertNotQuery('//a[@href="/admin/index/security"]'); $this->assertNotQuery('//a[@href="/admin/collectionroles"]'); $this->assertNotQuery('//a[@href="/admin/series"]'); - $this->assertNotQuery('//a[@href="/admin/language"]'); $this->assertNotQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertNotQuery('//a[@href="/admin/index/setup"]'); $this->assertNotQuery('//a[@href="/review"]'); diff --git a/tests/security/FullAdminTest.php b/tests/security/FullAdminTest.php index 091ef8b3c..969ecede0 100644 --- a/tests/security/FullAdminTest.php +++ b/tests/security/FullAdminTest.php @@ -63,7 +63,6 @@ public function testAdminMenuFiltering() $this->assertQuery('//a[@href="/admin/index/security"]'); $this->assertQuery('//a[@href="/admin/collectionroles"]'); $this->assertQuery('//a[@href="/admin/series"]'); - $this->assertQuery('//a[@href="/admin/language"]'); $this->assertQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertQuery('//a[@href="/admin/index/info"]'); $this->assertNotQuery('//a[@href="/review"]'); diff --git a/tests/security/FullAndPartialAdminTest.php b/tests/security/FullAndPartialAdminTest.php index 28d946ea2..e7474b9b8 100644 --- a/tests/security/FullAndPartialAdminTest.php +++ b/tests/security/FullAndPartialAdminTest.php @@ -63,7 +63,6 @@ public function testAdminMenuFiltering() $this->assertQuery('//a[@href="/admin/index/security"]'); $this->assertQuery('//a[@href="/admin/collectionroles"]'); $this->assertQuery('//a[@href="/admin/series"]'); - $this->assertQuery('//a[@href="/admin/language"]'); $this->assertQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertQuery('//a[@href="/admin/index/info"]'); $this->assertQuery('//a[@href="/admin/index/setup"]'); diff --git a/tests/security/LicencesAdminTest.php b/tests/security/LicencesAdminTest.php index 70b6e6ed8..97a97c8c4 100644 --- a/tests/security/LicencesAdminTest.php +++ b/tests/security/LicencesAdminTest.php @@ -63,7 +63,6 @@ public function testAdminMenuFiltering() $this->assertNotQuery('//a[@href="/admin/index/security"]'); $this->assertNotQuery('//a[@href="/admin/collectionroles"]'); $this->assertNotQuery('//a[@href="/admin/series"]'); - $this->assertNotQuery('//a[@href="/admin/language"]'); $this->assertNotQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertNotQuery('//a[@href="/admin/index/setup"]'); $this->assertNotQuery('//a[@href="/review"]'); diff --git a/tests/security/SecurityAdminTest.php b/tests/security/SecurityAdminTest.php index 2260573e1..8ad0b7bf5 100644 --- a/tests/security/SecurityAdminTest.php +++ b/tests/security/SecurityAdminTest.php @@ -62,7 +62,6 @@ public function testAdminMenuFiltering() $this->assertNotQuery('//a[@href="/admin/documents"]'); $this->assertNotQuery('//a[@href="/admin/licence"]'); $this->assertNotQuery('//a[@href="/admin/series"]'); - $this->assertNotQuery('//a[@href="/admin/language"]'); $this->assertNotQuery('//a[@href="/admin/dnbinstitute"]'); $this->assertQuery('//a[@href="/admin/index/info"]'); // Untermenü für Informationen $this->assertNotQuery('//a[@href="/review"]'); diff --git a/tests/support/AccessModuleAdminOneResourceOnlyTest.php b/tests/support/AccessModuleAdminOneResourceOnlyTest.php index cb1eb2201..fdbeaf96b 100644 --- a/tests/support/AccessModuleAdminOneResourceOnlyTest.php +++ b/tests/support/AccessModuleAdminOneResourceOnlyTest.php @@ -90,7 +90,6 @@ public function testAdminMenuFiltering() $this->assertElement('//a[@href="/admin/index/security"]', false); $this->assertElement('//a[@href="/admin/collectionroles"]', false); $this->assertElement('//a[@href="/admin/series"]', false); - $this->assertElement('//a[@href="/admin/language"]', false); $this->assertElement('//a[@href="/admin/dnbinstitute"]', false); $this->assertElement('//a[@href="/admin/index/setup"]', $this->acls['module_setup']); $this->assertElement('//a[@href="/review"]', false); diff --git a/tests/support/AccessModuleSetupAndAdminTest.php b/tests/support/AccessModuleSetupAndAdminTest.php index 913771298..245b0b2a5 100644 --- a/tests/support/AccessModuleSetupAndAdminTest.php +++ b/tests/support/AccessModuleSetupAndAdminTest.php @@ -92,7 +92,6 @@ public function testAdminMenuFiltering() $this->assertElement('//a[@href="/admin/index/security"]', $this->acls['module_admin']); $this->assertElement('//a[@href="/admin/collectionroles"]', $this->acls['module_admin']); $this->assertElement('//a[@href="/admin/series"]', $this->acls['module_admin']); - $this->assertElement('//a[@href="/admin/language"]', $this->acls['module_admin']); $this->assertElement('//a[@href="/admin/dnbinstitute"]', $this->acls['module_admin']); $this->assertElement('//a[@href="/admin/index/info"]', $this->acls['module_admin']); $this->assertElement('//a[@href="/admin/index/setup"]', $this->acls['module_admin']);