diff --git a/CHANGES.md b/CHANGES.md
index 1e2dd04f0..b8aa53f9c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,10 @@
# OPUS 4 Change Log
+## Release 4.8.0.8 - 2024-12-04
+
+https://github.com/OPUS4/application/issues/1253
+https://github.com/OPUS4/application/issues/1258
+
## Release 4.8.0.7 - 2024-10-22
https://github.com/OPUS4/application/issues/1243
diff --git a/README.md b/README.md
index ab14178c9..8ce05d98b 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ mostly.
## OPUS 4
-The current version of OPUS 4 is __4.8.0.7__. It is available on the [master][MASTER] branch and compatible with
+The current version of OPUS 4 is __4.8.0.8__. It is available on the [master][MASTER] branch and compatible with
PHP 7.1 to 8.1.
[Documentation][DOC]
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 01e4ee959..a7ce5701a 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,21 @@
# OPUS 4 Release Notes
+## Patch Release 4.8.0.8 - 2024-12-04
+
+Das Blockieren der Enter/Return-Taste wurde auf die Metadaten-Formulare
+im Publish-Modul und in der Administration beschränkt. In allen anderen
+Formularen verhält sich die Taste daher wieder wie vor OPUS 4.8.0.7.
+
+https://github.com/OPUS4/application/issues/1258
+
+Es wurden neue Konsolen-Kommandos für den Umgang mit Enrichments hinzugefügt.
+Alle OPUS 4 Kommandos können mit `bin/opus4` angezeigt werden. Das Kommando
+`enrichment:import` kann zum Beispiel verwendet werden, um in einer Yaml-Datei
+definierte Enrichments anzulegen. Beispiele für solche Konfigurationen finden
+sich in `tests/resources/enrichments`.
+
+https://github.com/OPUS4/application/issues/1253
+
## Patch Release 4.8.0.7 - 2024-10-22
Ein Fehler beim Drücken der Enter/Return-Taste in einfachen Text-Feldern
diff --git a/application/configs/application.ini b/application/configs/application.ini
index 1bcfe3a7e..76cc8169d 100644
--- a/application/configs/application.ini
+++ b/application/configs/application.ini
@@ -70,7 +70,7 @@ name = 'OPUS 4'
logoLink = home
security = 1
workspacePath = APPLICATION_PATH "/workspace"
-version = 4.8.0.7
+version = 4.8.0.8
update.latestVersionCheckUrl = "https://api.github.com/repos/opus4/application/releases/latest"
; Determines the implementation of the OPUS 4 data model
diff --git a/composer.json b/composer.json
index b14855003..95e9c3690 100644
--- a/composer.json
+++ b/composer.json
@@ -20,6 +20,7 @@
"ext-fileinfo": "*",
"ext-readline": "*",
"ext-sockets": "*",
+ "ext-yaml": "*",
"opus4/zf1-future": "1.21.*",
"jpgraph/jpgraph": "dev-master",
"opus4-repo/opus4-common": "^4.8",
@@ -34,6 +35,7 @@
"components/jqueryui": "1.12.*",
"oomphinc/composer-installers-extender": "^2.0",
"symfony/console": "*",
+ "symfony/yaml": "*",
"pear/log": "*"
},
"require-dev": {
diff --git a/library/Application/Configuration/EnrichmentConfigImporter.php b/library/Application/Configuration/EnrichmentConfigImporter.php
new file mode 100644
index 000000000..dce9b1fe8
--- /dev/null
+++ b/library/Application/Configuration/EnrichmentConfigImporter.php
@@ -0,0 +1,201 @@
+processConfig($config, $keyName);
+ }
+
+ /**
+ * @param string $yaml
+ * @param string|null $keyName
+ */
+ public function importYaml($yaml, $keyName = null)
+ {
+ $config = yaml_parse($yaml);
+
+ $this->processConfig($config, $keyName);
+ }
+
+ /**
+ * @param array $config
+ * @param string|null $keyName
+ */
+ protected function processConfig($config, $keyName = null)
+ {
+ if (! $config || ! is_array($config)) {
+ throw new InvalidArgumentException('First parameter should be an array');
+ }
+
+ $config = $this->changeKeysTolowerCase($config);
+
+ if (isset($config['enrichments'])) {
+ $enrichmentConfigs = $config['enrichments'];
+ } else {
+ if ($keyName !== null) {
+ $config['name'] = $keyName;
+ }
+ $enrichmentConfigs = [$config];
+ }
+
+ foreach ($enrichmentConfigs as $enrichment) {
+ $enrichmentKey = $this->createEnrichment($enrichment);
+ if ($enrichmentKey !== null) {
+ $name = $enrichmentKey->getName();
+ $this->getOutput()->writeln("Created enrichment key '{$name}'");
+ }
+ }
+ }
+
+ /**
+ * @param array $config
+ * @return EnrichmentKeyInterface|null
+ */
+ public function createEnrichment($config)
+ {
+ $name = $config['name'];
+
+ $enrichmentKey = EnrichmentKey::fetchByName($name);
+
+ if ($enrichmentKey !== null) {
+ $this->getOutput()->writeln("Enrichment '{$enrichmentKey}' already exists");
+ return null;
+ }
+
+ $enrichmentKey = EnrichmentKey::new();
+
+ $enrichmentKey->setName($name);
+
+ $type = null;
+
+ if (isset($config['type'])) {
+ $type = ucfirst($config['type'] . 'Type');
+ $enrichmentKey->setType($type); // TODO make 'Type' suffix unnecessary
+ }
+
+ if (isset($config['options']) && $type !== null) {
+ $typeClass = 'Opus\\Enrichment\\' . $type;
+ $enrichmentType = new $typeClass();
+ $options = $config['options'];
+ if (is_array($options)) {
+ $enrichmentType->setOptions($options);
+ $enrichmentKey->setOptions($enrichmentType->getOptions());
+ } else {
+ $enrichmentType->setOptionsFromString($options);
+ $enrichmentKey->setOptions($enrichmentType->getOptions());
+ }
+ }
+
+ $enrichmentKey->store();
+
+ if (isset($config['translations'])) {
+ $this->createTranslations($name, $config['translations']);
+ }
+
+ return $enrichmentKey;
+ }
+
+ /**
+ * @param string $name
+ * @param array $translations
+ */
+ public function createTranslations($name, $translations)
+ {
+ $helper = new Admin_Model_EnrichmentKeys();
+ $keys = array_keys($translations);
+ $supportedKeys = $helper->getSupportedKeys();
+ $unsupportedKeys = array_diff($keys, $supportedKeys);
+
+ if (count($unsupportedKeys) > 0) {
+ foreach ($unsupportedKeys as $key) {
+ $this->getOutput()->writeln("Unsupported translation key: {$key}");
+ }
+ }
+
+ $helper->createTranslations($name, null, $translations);
+ }
+
+ /**
+ * @param OutputInterface $output
+ * @return $this
+ */
+ public function setOutput($output)
+ {
+ $this->output = $output;
+ return $this;
+ }
+
+ /**
+ * @return OutputInterface
+ */
+ public function getOutput()
+ {
+ if ($this->output === null) {
+ $this->output = new NullOutput();
+ }
+ return $this->output;
+ }
+
+ /**
+ * @param array $config
+ * @return array
+ */
+ protected function changeKeysTolowerCase($config)
+ {
+ return array_map(function ($item) {
+ if (is_array($item)) {
+ $item = $this->changeKeysToLowerCase($item);
+ }
+ return $item;
+ }, array_change_key_case($config, CASE_LOWER));
+ }
+}
diff --git a/library/Application/Console/App.php b/library/Application/Console/App.php
index e3da9f7a6..1788dde04 100644
--- a/library/Application/Console/App.php
+++ b/library/Application/Console/App.php
@@ -65,6 +65,13 @@ public function __construct()
$this->add(new Application_Console_Debug_DocumentXmlCommand());
$this->add(new CoverGenerateCommand());
+ // TODO use ModelCommandProvider (with OPUS 4.8.1)
+ $this->add(new Application_Console_Model_EnrichmentImportCommand());
+ $this->add(new Application_Console_Model_EnrichmentListCommand());
+ $this->add(new Application_Console_Model_EnrichmentExportCommand());
+ $this->add(new Application_Console_Model_EnrichmentRenameCommand());
+ $this->add(new Application_Console_Model_EnrichmentDeleteCommand());
+
$this->setDefaultCommand('list');
}
}
diff --git a/library/Application/Console/Model/EnrichmentDeleteCommand.php b/library/Application/Console/Model/EnrichmentDeleteCommand.php
new file mode 100644
index 000000000..ecf1f62ab
--- /dev/null
+++ b/library/Application/Console/Model/EnrichmentDeleteCommand.php
@@ -0,0 +1,112 @@
+enrichment:delete> command can be used to delete enrichments. The command
+also removes the translations associated with the enrichment.
+EOT;
+
+ $this->setName('enrichment:delete')
+ ->setDescription('Rename enrichment')
+ ->setHelp($help)
+ ->addArgument(
+ self::ARGUMENT_KEY,
+ InputArgument::OPTIONAL,
+ 'Enrichment key'
+ )->addOption(
+ self::OPTION_FORCE,
+ 'f',
+ InputOption::VALUE_NONE,
+ 'Do not prompt for confirmation.'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $key = $input->getArgument(self::ARGUMENT_KEY);
+
+ if ($key === null) {
+ $output->writeln('Enrichment key is required');
+ return 1;
+ }
+
+ $enrichment = EnrichmentKey::fetchByName($key);
+
+ if ($enrichment === null) {
+ $output->writeln("Enrichment key \"{$key}\" not found");
+ return 1;
+ }
+
+ if (! $input->getOption(self::OPTION_FORCE)) {
+ $questionText = "Do you want to remove enrichment key \"{$key}\" (Y/n)?";
+ $confirmation = new ConfirmationQuestion($questionText, true);
+ $question = $this->getHelper('question');
+
+ if (! $question->ask($input, $output, $confirmation)) {
+ $output->writeln("Not removing enrichment key \"{$key}\".");
+ return 0;
+ }
+ }
+
+ $output->writeln("Removing enrichment key \"{$key}\".");
+ $enrichment->delete();
+
+ $output->writeln("Removing translations for enrichment key \"{$key}\".");
+ $helper = new Admin_Model_EnrichmentKeys();
+ $helper->removeTranslations($key);
+
+ return 0;
+ }
+}
diff --git a/library/Application/Console/Model/EnrichmentExportCommand.php b/library/Application/Console/Model/EnrichmentExportCommand.php
new file mode 100644
index 000000000..0c27ad92a
--- /dev/null
+++ b/library/Application/Console/Model/EnrichmentExportCommand.php
@@ -0,0 +1,128 @@
+enrichment:export> command allows exporting the configuration of
+one or all enrichment keys.
+EOT;
+
+ $this->setName('enrichment:export')
+ ->setDescription('Export enrichment configurations')
+ ->setHelp($help)
+ ->addArgument(
+ self::ARGUMENT_KEYS,
+ InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
+ 'Enrichment key(s)'
+ )->addOption(
+ self::OPTION_OUTPUT_FILE,
+ 'o',
+ InputOption::VALUE_REQUIRED,
+ 'Name of output file'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $keys = $input->getArgument(self::ARGUMENT_KEYS);
+
+ if (count($keys) === 0) {
+ $keys = EnrichmentKey::getAll();
+ } else {
+ foreach ($keys as $key) {
+ $enrichment = EnrichmentKey::fetchByName($key);
+
+ if ($enrichment === null) {
+ $output->writeln("Enrichment key \"{$key}\" not found");
+ return 1;
+ }
+ }
+ }
+
+ if (count($keys) === 0) {
+ $output->writeln("No enrichment keys found");
+ return 0;
+ }
+
+ $helper = new Admin_Model_EnrichmentKeys();
+
+ if (count($keys) === 1) {
+ $data = $helper->getEnrichmentConfig($keys[0]);
+ } else {
+ $enrichments = [];
+ foreach ($keys as $key) {
+ $enrichments[] = $helper->getEnrichmentConfig($key);
+ }
+ $data['enrichments'] = $enrichments;
+ }
+
+ // Export lowercase keys
+ $data = array_change_key_case($data, CASE_LOWER);
+ $yaml = Yaml::dump($data, 6, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
+
+ // WORKAROUND: put first line of collection item behind dash
+ $yaml = preg_replace('/\-\n\s+/', '- ', $yaml);
+
+ $outputFile = $input->getOption(self::OPTION_OUTPUT_FILE);
+
+ if ($outputFile === null) {
+ $output->writeln($yaml);
+ } else {
+ file_put_contents($outputFile, $yaml);
+ }
+
+ return 0;
+ }
+}
diff --git a/library/Application/Console/Model/EnrichmentImportCommand.php b/library/Application/Console/Model/EnrichmentImportCommand.php
new file mode 100644
index 000000000..5405ceaa3
--- /dev/null
+++ b/library/Application/Console/Model/EnrichmentImportCommand.php
@@ -0,0 +1,84 @@
+enrichment:import> command can be used to import Enrichment
+configurations using Yaml files.
+EOT;
+
+ $this->setName('enrichment:import')
+ ->setDescription('Import Enrichment configuration')
+ ->setHelp($help)
+ ->addArgument(
+ self::ARGUMENT_FILE,
+ InputArgument::REQUIRED,
+ 'Yaml file containing configuration'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $file = $input->getArgument(self::ARGUMENT_FILE);
+
+ if (! file_exists($file)) {
+ $output->writeln('Input file not found>');
+ return 1;
+ }
+
+ if (! is_readable($file)) {
+ $output->writeln('Input file not readable>');
+ return 1;
+ }
+
+ $importer = new Application_Configuration_EnrichmentConfigImporter();
+ $importer->setOutput($output);
+
+ $importer->import($file);
+
+ return 0;
+ }
+}
diff --git a/library/Application/Console/Model/EnrichmentListCommand.php b/library/Application/Console/Model/EnrichmentListCommand.php
new file mode 100644
index 000000000..326761d22
--- /dev/null
+++ b/library/Application/Console/Model/EnrichmentListCommand.php
@@ -0,0 +1,81 @@
+enrichment:list> command lists all enrichments present in the
+database.
+EOT;
+
+ $this->setName('enrichment:list')
+ ->setDescription('Lists enrichments')
+ ->setHelp($help);
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $allKeys = EnrichmentKey::getAll();
+ $referencedKeys = EnrichmentKey::getAllReferenced();
+
+ $rows = [];
+
+ foreach ($allKeys as $key) {
+ $rows[] = [
+ $key,
+ in_array($key, $referencedKeys) ? 'used' : '',
+ ];
+ }
+
+ $table = new Table($output);
+ $table->setHeaders(['Enrichment-Key', 'Used'])
+ ->setRows($rows);
+ $table->render();
+
+ return 0;
+ }
+}
diff --git a/library/Application/Console/Model/EnrichmentRenameCommand.php b/library/Application/Console/Model/EnrichmentRenameCommand.php
new file mode 100644
index 000000000..4bfb7a5fe
--- /dev/null
+++ b/library/Application/Console/Model/EnrichmentRenameCommand.php
@@ -0,0 +1,110 @@
+enrichment:rename> command can be used to rename enrichments.
+EOT;
+
+ $this->setName('enrichment:rename')
+ ->setDescription('Rename enrichment')
+ ->setHelp($help)
+ ->addArgument(
+ self::ARGUMENT_KEY,
+ InputArgument::REQUIRED,
+ 'Enrichment key'
+ )->addArgument(
+ self::ARGUMENT_NEW_KEY,
+ InputArgument::REQUIRED,
+ 'New Enrichment key'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $key = $input->getArgument(self::ARGUMENT_KEY);
+
+ if ($key === null) {
+ $output->writeln('Enrichment key is required.>');
+ return 1;
+ }
+
+ $newKey = $input->getArgument(self::ARGUMENT_NEW_KEY);
+
+ if ($newKey === null) {
+ $output->writeln('New enrichment key name is required.>');
+ return 1;
+ }
+
+ $enrichment = EnrichmentKey::fetchByName($key);
+
+ if ($enrichment === null) {
+ $output->writeln("Enrichment key \"{$key}\" not found.");
+ return 1;
+ }
+
+ $newEnrichment = EnrichmentKey::fetchByName($newKey);
+
+ if ($newEnrichment !== null) {
+ $output->writeln("Enrichment key \"{$newKey}\" already exists.");
+ return 1;
+ }
+
+ $output->writeln("Renaming key \"{$key}\" to \"{$newKey}\".");
+ $enrichment->rename($newKey);
+ $enrichment->setName($newKey);
+ $enrichment->store();
+
+ $output->writeln("Renaming translations for enrichment key \"{$newKey}\"");
+ $helper = new Admin_Model_EnrichmentKeys();
+ $helper->createTranslations($newKey, $key);
+
+ return 0;
+ }
+}
diff --git a/modules/admin/controllers/DocumentController.php b/modules/admin/controllers/DocumentController.php
index 606b4de25..614976eba 100644
--- a/modules/admin/controllers/DocumentController.php
+++ b/modules/admin/controllers/DocumentController.php
@@ -51,6 +51,7 @@ public function init()
{
parent::init();
$this->documentsHelper = $this->_helper->getHelper('Documents');
+ $this->view->headScript()->prependFile($this->view->layoutPath() . '/js/form-enter.js');
}
/**
diff --git a/modules/admin/forms/EnrichmentKey.php b/modules/admin/forms/EnrichmentKey.php
index eb4a73c85..ddc462dcd 100644
--- a/modules/admin/forms/EnrichmentKey.php
+++ b/modules/admin/forms/EnrichmentKey.php
@@ -175,6 +175,8 @@ public function populateFromModel($enrichmentKey)
$enrichmentType = $this->initEnrichmentType($enrichmentKey->getType());
if ($enrichmentType !== null) {
+ // TODO this should not be necessary - The EnrichmentType defines the options, but the options are not for
+ // the type, but for the EnrichmentKey.
$enrichmentType->setOptions($enrichmentKey->getOptions());
$optionsElement = $this->getElement(self::ELEMENT_OPTIONS);
diff --git a/modules/admin/models/EnrichmentKeys.php b/modules/admin/models/EnrichmentKeys.php
index 9200d7421..07770a189 100644
--- a/modules/admin/models/EnrichmentKeys.php
+++ b/modules/admin/models/EnrichmentKeys.php
@@ -29,6 +29,7 @@
* @license http://www.gnu.org/licenses/gpl.html General Public License
*/
+use Opus\Common\EnrichmentKey;
use Opus\Translate\Dao;
/**
@@ -41,12 +42,12 @@ class Admin_Model_EnrichmentKeys extends Application_Model_Abstract
{
/** @var string[] */
private $translationKeyPatterns = [
- 'hint_Enrichment%s',
- 'header_Enrichment%s',
- 'group%s',
- 'hint_group%s',
- 'button_label_add_one_moreEnrichment%s',
- 'button_label_deleteEnrichment%s',
+ 'hint' => 'hint_Enrichment%s',
+ 'header' => 'header_Enrichment%s',
+ 'group' => 'group%s',
+ 'groupHint' => 'hint_group%s',
+ 'buttonAdd' => 'button_label_add_one_moreEnrichment%s',
+ 'buttonDelete' => 'button_label_deleteEnrichment%s',
];
/**
@@ -110,36 +111,85 @@ public function setProtectedEnrichmentKeys($keys)
*
* @param string $name Name of enrichment
* @param string|null $oldName Optionally old name if it has been changed
+ * @param array|null $translations
*
* TODO create keys if they don't exist
* TODO what happens if renameKey into keys that already exist?
+ * TODO support more languages
*/
- public function createTranslations($name, $oldName = null)
+ public function createTranslations($name, $oldName = null, $translations = null)
{
$patterns = $this->translationKeyPatterns;
$database = new Dao();
$manager = new Application_Translate_TranslationManager();
+ if ($translations === null) {
+ $translations = [];
+ }
+
if ($oldName !== null && $name !== $oldName) {
+ $patterns['label'] = 'Enrichment%s'; // TODO avoid custom handling for 'label'
+
foreach ($patterns as $pattern) {
$key = sprintf($pattern, $name);
$oldKey = sprintf($pattern, $oldName);
$database->renameKey($oldKey, $key, 'default');
}
} else {
- foreach ($patterns as $pattern) {
+ if (isset($translations['label'])) {
+ $patterns['label'] = 'Enrichment%s'; // TODO avoid custom handling for 'label'
+ }
+ foreach ($patterns as $patternName => $pattern) {
$key = sprintf($pattern, $name);
if (! $manager->keyExists($key)) {
+ $enValue = $name;
+ if (isset($translations[$patternName]['en'])) {
+ $enValue = $translations[$patternName]['en'];
+ }
+
+ $deValue = $name;
+ if (isset($translations[$patternName]['de'])) {
+ $deValue = $translations[$patternName]['de'];
+ }
+
$database->setTranslation($key, [
- 'en' => $name,
- 'de' => $name,
+ 'en' => $enValue,
+ 'de' => $deValue,
], 'default');
}
}
}
}
+ /**
+ * @param string $name Name of enrichment key
+ * @return string[]
+ *
+ * TODO 'label' translation handled separately (here and in admin form) - unify handling?
+ */
+ public function getTranslations($name)
+ {
+ $patterns = $this->translationKeyPatterns;
+
+ $patterns['label'] = 'Enrichment%s';
+
+ $manager = new Application_Translate_TranslationManager();
+
+ $translations = [];
+
+ $allTranslations = $manager->getMergedTranslations();
+
+ foreach ($patterns as $patternName => $pattern) {
+ $key = sprintf($pattern, $name);
+ if (isset($allTranslations[$key]['translations'])) {
+ $translations[$patternName] = $allTranslations[$key]['translations'];
+ }
+ }
+
+ return $translations;
+ }
+
/**
* Remove translation keys if enrichment is deleted.
*
@@ -151,6 +201,8 @@ public function removeTranslations($name)
$database = new Dao();
+ $patterns['label'] = 'Enrichment%s'; // TODO avoid custom handling for 'label'
+
foreach ($patterns as $pattern) {
$key = sprintf($pattern, $name);
$database->remove($key, 'default');
@@ -164,4 +216,50 @@ public function getKeyPatterns()
{
return $this->translationKeyPatterns;
}
+
+ /**
+ * @param string $name
+ * @return string[]
+ */
+ public function getEnrichmentConfig($name)
+ {
+ $enrichment = EnrichmentKey::fetchByName($name);
+ $enrichmentConfig = $enrichment->toArray();
+
+ // remove NULL values
+ $enrichmentConfig = array_filter($enrichmentConfig, function ($value) {
+ return $value !== null;
+ });
+
+ // remove 'Type' from type name (TODO this should not be necessary later)
+ if (isset($enrichmentConfig['Type'])) {
+ $type = preg_replace('/Type$/', '', $enrichmentConfig['Type']);
+ $enrichmentConfig['Type'] = $type;
+ }
+
+ // add translations to configuration
+ $translations = $this->getTranslations($name);
+ if (count($translations) > 0) {
+ $enrichmentConfig['translations'] = $translations;
+ }
+
+ // handle options
+ if (isset($enrichmentConfig['Options'])) {
+ $options = json_decode($enrichmentConfig['Options'], true);
+ $enrichmentConfig['Options'] = $options;
+ }
+
+ // use lowercase keys in yaml
+ $enrichmentConfig = array_change_key_case($enrichmentConfig, CASE_LOWER);
+
+ return $enrichmentConfig;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getSupportedKeys()
+ {
+ return array_keys($this->getKeyPatterns());
+ }
}
diff --git a/modules/publish/controllers/FormController.php b/modules/publish/controllers/FormController.php
index 7ae50b7b2..a1467fc76 100644
--- a/modules/publish/controllers/FormController.php
+++ b/modules/publish/controllers/FormController.php
@@ -53,6 +53,7 @@ public function init()
{
$this->session = new Zend_Session_Namespace('Publish');
parent::init();
+ $this->view->headScript()->prependFile($this->view->layoutPath() . '/js/form-enter.js');
}
/**
diff --git a/public/layouts/opus4/js/form-enter.js b/public/layouts/opus4/js/form-enter.js
new file mode 100644
index 000000000..6b48659bd
--- /dev/null
+++ b/public/layouts/opus4/js/form-enter.js
@@ -0,0 +1,41 @@
+/**
+ * This file is part of OPUS. The software OPUS has been originally developed
+ * at the University of Stuttgart with funding from the German Research Net,
+ * the Federal Department of Higher Education and Research and the Ministry
+ * of Science, Research and the Arts of the State of Baden-Wuerttemberg.
+ *
+ * OPUS 4 is a complete rewrite of the original OPUS software and was developed
+ * by the Stuttgart University Library, the Library Service Center
+ * Baden-Wuerttemberg, the Cooperative Library Network Berlin-Brandenburg,
+ * the Saarland University and State Library, the Saxon State Library -
+ * Dresden State and University Library, the Bielefeld University Library and
+ * the University Library of Hamburg University of Technology with funding from
+ * the German Research Foundation and the European Regional Development Fund.
+ *
+ * LICENCE
+ * OPUS is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the Licence, or any later version.
+ * OPUS is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details. You should have received a copy of the GNU General Public License
+ * 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) 2024, OPUS 4 development team
+ * @license http://www.gnu.org/licenses/gpl.html General Public License
+ */
+
+$(function () {
+
+ // Prevent submission of form when Enter/Return is pressed in a simple text input
+ $('form').on('keydown', e => {
+ if (e.key === 'Enter') {
+ if ($(e.target).is("input[type='text']")) {
+ e.preventDefault();
+ }
+ }
+ });
+
+});
diff --git a/public/layouts/opus4/js/submit.js b/public/layouts/opus4/js/submit.js
index 73082554c..fc360bbce 100644
--- a/public/layouts/opus4/js/submit.js
+++ b/public/layouts/opus4/js/submit.js
@@ -36,13 +36,4 @@ $(function () {
});
});
- // Prevent submission of form when Enter/Return is pressed in a simple text input
- $('form').on('keydown', e => {
- if (e.key === 'Enter') {
- if ($(e.target).is("input[type='text']")) {
- e.preventDefault();
- }
- }
- });
-
});
diff --git a/tests/library/Application/Configuration/EnrichmentConfigImporterTest.php b/tests/library/Application/Configuration/EnrichmentConfigImporterTest.php
new file mode 100644
index 000000000..7b1ed2a5e
--- /dev/null
+++ b/tests/library/Application/Configuration/EnrichmentConfigImporterTest.php
@@ -0,0 +1,267 @@
+importer = new Application_Configuration_EnrichmentConfigImporter();
+ }
+
+ public function testImportSingleEnrichmentFromString()
+ {
+ $yaml = <<importer->importYaml($yaml);
+
+ $enrichment = EnrichmentKey::fetchByName('testKey1');
+
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+ }
+
+ public function testImportSelectEnrichmentConfig()
+ {
+ $keyName = 'conferenceType';
+
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/conferenceType.yml';
+
+ $this->importer->import($yamlFile);
+
+ $enrichmentKey = EnrichmentKey::fetchByName($keyName);
+
+ $this->assertNotNull($enrichmentKey);
+
+ $this->addModelToCleanup($enrichmentKey);
+
+ $this->assertEquals($keyName, $enrichmentKey->getName());
+ $this->assertEquals('SelectType', $enrichmentKey->getType());
+
+ $options = $enrichmentKey->getOptions();
+
+ $enrichmentType = new SelectType();
+ $enrichmentType->setOptions($options);
+
+ $this->assertEquals('strict', $enrichmentType->getValidation());
+ $this->assertEquals([
+ 'Konferenzband',
+ 'Konferenzartikel',
+ 'Konferenz-Poster',
+ 'Konferenz-Abstract',
+ 'Sonstiges',
+ ], $enrichmentType->getValues());
+
+ $helper = new Admin_Model_EnrichmentKeys();
+ $translations = $helper->getTranslations($keyName);
+ $helper->removeTranslations($keyName);
+
+ $this->assertCount(7, $translations);
+ $this->assertEquals([
+ 'de' => 'Art der Konferenzveröffentlichung',
+ 'en' => 'Conference Type',
+ ], $translations['label']);
+ $this->assertEquals([
+ 'de' => 'conferenceType',
+ 'en' => 'conferenceType',
+ ], $translations['hint']);
+ }
+
+ public function testImportMultipleEnrichmentConfigs()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/multipleKeys.yml';
+
+ $this->importer->import($yamlFile);
+
+ $keys = [
+ 'testKey1',
+ 'testKey2',
+ 'testKey3',
+ 'testKey4',
+ ];
+
+ foreach ($keys as $key) {
+ $enrichment = EnrichmentKey::fetchByName($key);
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+ }
+ }
+
+ public function testKeysAreHandledCaseInsensitive()
+ {
+ $yaml = <<importer->importYaml($yaml);
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey1');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $helper = new Admin_Model_EnrichmentKeys();
+ $translations = $helper->getTranslations('enrichmentKey1');
+ $helper->removeTranslations('enrichmentKey1');
+
+ $this->assertCount(7, $translations);
+ $this->assertEquals([
+ 'de' => 'EnrichmentKey1de',
+ 'en' => 'EnrichmentKey1en',
+ ], $translations['label']);
+ }
+
+ public function testEnrichmentAlreadyExists()
+ {
+ $this->assertNotNull(EnrichmentKey::fetchByName('Country'));
+
+ $yaml = <<importer->importYaml($yaml);
+
+ $enrichment = EnrichmentKey::fetchByName('Country');
+
+ $this->assertNotNull($enrichment);
+ }
+
+ public function testUseDifferentEnrichmentKeyName()
+ {
+ $yaml = <<importer->importYaml($yaml, 'enrichmentKey2');
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey1');
+ $this->assertNull($enrichment);
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey2');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+ }
+
+ public function testUseKeyNameWhenImportingMultipleKeys()
+ {
+ $yaml = <<importer->importYaml($yaml, 'enrichmentKey3');
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey1');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey2');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $enrichment = EnrichmentKey::fetchByName('enrichmentKey3');
+ $this->assertNull($enrichment);
+ }
+
+ public function testImportSelectEnrichmentWithSimpleOptions()
+ {
+ $yaml = <<importer->importYaml($yaml);
+
+ $enrichment = EnrichmentKey::fetchByName('color');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $enrichmentType = new SelectType();
+ $enrichmentType->setOptions($enrichment->getOptions());
+
+ $this->assertEquals('none', $enrichmentType->getValidation());
+ $this->assertEquals([
+ 'red',
+ 'green',
+ 'blue',
+ 'yellow',
+ ], $enrichmentType->getValues());
+ }
+
+ public function testTranslationWithUnknownKey()
+ {
+ $yaml = <<importer->setOutput($output);
+ $this->importer->importYaml($yaml);
+
+ $enrichment = EnrichmentKey::fetchByName('color');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $helper = new Admin_Model_EnrichmentKeys();
+ $translations = $helper->getTranslations('color');
+
+ $this->assertCount(6, $translations); // TODO label should be added automatically
+
+ $this->assertStringContainsString('Unsupported translation key: category', $output->fetch());
+ }
+}
diff --git a/tests/library/Application/Console/Model/EnrichmentDeleteCommandTest.php b/tests/library/Application/Console/Model/EnrichmentDeleteCommandTest.php
new file mode 100644
index 000000000..d3cc14999
--- /dev/null
+++ b/tests/library/Application/Console/Model/EnrichmentDeleteCommandTest.php
@@ -0,0 +1,170 @@
+setApplication($app);
+
+ $this->tester = new CommandTester($command);
+
+ $enrichment = EnrichmentKey::new();
+ $enrichment->setName(self::TEST_ENRICHMENT_KEY);
+ $enrichment->store();
+ }
+
+ public function tearDown(): void
+ {
+ $enrichment = EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY);
+ if ($enrichment !== null) {
+ $enrichment->delete();
+ }
+
+ parent::tearDown();
+ }
+
+ public function testDeleteWithoutEnrichmentKey()
+ {
+ $this->tester->execute([]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key is required', $output);
+ }
+
+ public function testDeleteEnrichmentWithoutConfirmation()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ '-f' => true,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+ }
+
+ public function testDeleteEnrichmentWithoutConfirmationUsingLongOption()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ '--force' => true,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+ }
+
+ public function testDeleteEnrichmentWithConfirmation()
+ {
+ $this->tester->setInputs(['y']);
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+ }
+
+ public function testDeleteEnrichmentWithConfirmationYesIsDefault()
+ {
+ $this->markTestSkipped('Breaks with PHP 7 and Symfony Console 4');
+
+ $this->tester->setInputs(['']); // pressing enter at confirmation step
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+ }
+
+ public function testCancelDeletionAtConfirmation()
+ {
+ $this->tester->setInputs(['n']); // pressing enter at confirmation step
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ ]);
+
+ $this->assertNotNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+ }
+
+ public function testDeleteUnknownEnrichment()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => 'unknownEnrichmentKey',
+ '-f' => true,
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key "unknownEnrichmentKey" not found', $output);
+ $this->assertNotNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY)); // no side effects
+ }
+
+ public function testDeletionRemovesTranslations()
+ {
+ $helper = new Admin_Model_EnrichmentKeys();
+
+ $helper->createTranslations(self::TEST_ENRICHMENT_KEY);
+
+ $translations = $helper->getTranslations(self::TEST_ENRICHMENT_KEY);
+
+ $this->assertGreaterThan(1, count($translations));
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentDeleteCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ '-f' => true,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY)); // no side effects
+
+ $translations = $helper->getTranslations(self::TEST_ENRICHMENT_KEY);
+
+ $this->assertCount(0, $translations);
+ }
+}
diff --git a/tests/library/Application/Console/Model/EnrichmentExportCommandTest.php b/tests/library/Application/Console/Model/EnrichmentExportCommandTest.php
new file mode 100644
index 000000000..c35fee052
--- /dev/null
+++ b/tests/library/Application/Console/Model/EnrichmentExportCommandTest.php
@@ -0,0 +1,224 @@
+setApplication($app);
+
+ $this->tester = new CommandTester($command);
+ }
+
+ public function testExportEnrichment()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => ['opus.import.checksum'],
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $expected = <<assertEquals($expected, trim($output)); // trim additional line breaks at end of output
+ }
+
+ public function testExportEnrichmentWithTranslations()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => ['Country'],
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $expected = <<assertEquals($expected, trim($output)); // trim additional line breaks at end of output
+ }
+
+ public function testExportMultipleEnrichmentKeys()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => [
+ 'opus.import.date',
+ 'opus.import.file',
+ ],
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('enrichments:', $output);
+ $this->assertStringContainsString(' - name: opus.import.date', $output);
+ $this->assertStringContainsString(' - name: opus.import.file', $output);
+ }
+
+ public function testExportAllEnrichments()
+ {
+ $this->tester->execute([]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('enrichments:', $output);
+
+ $exportCount = substr_count($output, '- name:');
+
+ $allKeys = EnrichmentKey::getKeys();
+
+ $this->assertEquals(count($allKeys), $exportCount);
+ }
+
+ public function testUnknownEnrichmentKey()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => [
+ 'UnknownKey',
+ ],
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key "UnknownKey" not found', $output);
+ }
+
+ public function testExportMultipleEnrichmentKeysWithUnknownKeys()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => [
+ 'Country',
+ 'UnknownKey1',
+ 'UnknownKey2',
+ ],
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key "UnknownKey1" not found', $output);
+ $this->assertStringNotContainsString('Enrichment key "UnknownKey2" not found', $output);
+ }
+
+ public function testExportSelectEnrichment()
+ {
+ $enrichmentKey = EnrichmentKey::new();
+ $enrichmentKey->setName('testSelect');
+ $enrichmentKey->setType('SelectType');
+
+ $selectType = new SelectType();
+ $selectType->setOptions([
+ 'validation' => 'strict',
+ 'values' => [
+ 'Item1',
+ 'Item2',
+ 'Item3',
+ ],
+ ]);
+
+ $enrichmentKey->setOptions($selectType->getOptions());
+ $enrichmentKey->store();
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => ['testSelect'],
+ ]);
+
+ // cleanup before checks
+ $enrichmentKey->delete();
+
+ $output = $this->tester->getDisplay();
+
+ $expected = <<assertEquals($expected, trim($output));
+ }
+
+ public function testExportEnrichmentToOutputFile()
+ {
+ $tempFile = $this->getTempFile();
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentExportCommand::ARGUMENT_KEYS => ['Country'],
+ '--outputFile' => $tempFile,
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertEmpty($output);
+
+ $yaml = file_get_contents($tempFile);
+
+ $expected = <<assertEquals($expected, trim($yaml));
+ }
+}
diff --git a/tests/library/Application/Console/Model/EnrichmentImportCommandTest.php b/tests/library/Application/Console/Model/EnrichmentImportCommandTest.php
new file mode 100644
index 000000000..9da69fb66
--- /dev/null
+++ b/tests/library/Application/Console/Model/EnrichmentImportCommandTest.php
@@ -0,0 +1,228 @@
+setApplication($app);
+
+ $this->tester = new CommandTester($command);
+ }
+
+ public function testImportSingleEnrichment()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/singleKey.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $enrichment = EnrichmentKey::fetchByName('singleEnrichmentKey');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $this->assertStringContainsString('Created enrichment key \'singleEnrichmentKey\'', $output);
+ }
+
+ public function testImportEnrichmentAlreadyExists()
+ {
+ $enrichment = EnrichmentKey::new();
+ $enrichment->setName('singleEnrichmentKey');
+ $enrichment->store();
+
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/singleKey.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $enrichment = EnrichmentKey::fetchByName('singleEnrichmentKey');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $this->assertStringContainsString('Enrichment \'singleEnrichmentKey\' already exists', $output);
+ }
+
+ public function testImportMultipleEnrichments()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/multipleKeys.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $keys = [
+ 'testKey1',
+ 'testKey2',
+ 'testKey3',
+ 'testKey4',
+ ];
+
+ $output = $this->tester->getDisplay();
+
+ foreach ($keys as $key) {
+ $enrichment = EnrichmentKey::fetchByName($key);
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+ }
+
+ foreach ($keys as $key) {
+ $this->assertStringContainsString("Created enrichment key '{$key}'", $output);
+ }
+ }
+
+ public function testImportMultipleEnrichmentsOneAlreadyExists()
+ {
+ $enrichment = EnrichmentKey::new();
+ $enrichment->setName('testKey4');
+ $enrichment->store();
+
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/multipleKeys.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $keys = [
+ 'testKey1',
+ 'testKey2',
+ 'testKey3',
+ 'testKey4',
+ ];
+
+ $output = $this->tester->getDisplay();
+
+ foreach ($keys as $key) {
+ $enrichment = EnrichmentKey::fetchByName($key);
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+ }
+
+ array_pop($keys);
+
+ foreach ($keys as $key) {
+ $this->assertStringContainsString("Created enrichment key '{$key}'", $output);
+ }
+
+ $this->assertStringContainsString('Enrichment \'testKey4\' already exists', $output);
+ }
+
+ public function testImportFileNotFound()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/unknownFile.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Input file not found', $output);
+ }
+
+ public function testImportEnrichmentWithOptions()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/simpleOption.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $enrichment = EnrichmentKey::fetchByName('conferenceType');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $selectType = new SelectType();
+
+ $selectType->setOptions($enrichment->getOptions());
+
+ $this->assertEquals('none', $selectType->getValidation());
+ $this->assertEquals([
+ 'Konferenzband',
+ 'Konferenzartikel',
+ 'Konferenz-Poster',
+ 'Konferenz-Abstract',
+ 'Sonstiges',
+ ], $selectType->getValues());
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString("Created enrichment key 'conferenceType'", $output);
+ }
+
+ public function testImportEnrichmentWithTranslations()
+ {
+ $yamlFile = APPLICATION_PATH . '/tests/resources/enrichments/simpleOption.yml';
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentImportCommand::ARGUMENT_FILE => $yamlFile,
+ ]);
+
+ $enrichment = EnrichmentKey::fetchByName('conferenceType');
+ $this->assertNotNull($enrichment);
+ $this->addModelToCleanup($enrichment);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString("Created enrichment key 'conferenceType'", $output);
+
+ $helper = new Admin_Model_EnrichmentKeys();
+
+ $translations = $helper->getTranslations('conferenceType');
+
+ $this->assertNotEmpty($translations);
+ $this->assertEquals([
+ 'de' => 'Art der Konferenzveröffentlichung',
+ 'en' => 'Conference Type',
+ ], $translations['label']);
+ }
+}
diff --git a/tests/library/Application/Console/Model/EnrichmentListCommandTest.php b/tests/library/Application/Console/Model/EnrichmentListCommandTest.php
new file mode 100644
index 000000000..2a89dd307
--- /dev/null
+++ b/tests/library/Application/Console/Model/EnrichmentListCommandTest.php
@@ -0,0 +1,58 @@
+setApplication($app);
+
+ $tester = new CommandTester($command);
+
+ $tester->execute([]);
+
+ $output = $tester->getDisplay();
+
+ $this->assertRegExp('/^| Enrichment-Key\s+\| Used \|/', $output);
+ $this->assertRegExp('/^| BibtexRecord\s+\|\s+\|/', $output);
+ $this->assertRegExp('/^| ConstributorsName\s+\| used \|/', $output);
+ $this->assertRegExp('/^| validtestkey\s+\| used \|/', $output);
+ }
+}
diff --git a/tests/library/Application/Console/Model/EnrichmentRenameCommandTest.php b/tests/library/Application/Console/Model/EnrichmentRenameCommandTest.php
new file mode 100644
index 000000000..90a6fe0b5
--- /dev/null
+++ b/tests/library/Application/Console/Model/EnrichmentRenameCommandTest.php
@@ -0,0 +1,166 @@
+setApplication($app);
+
+ $this->tester = new CommandTester($command);
+
+ $enrichmentKey = EnrichmentKey::new();
+ $enrichmentKey->setName(self::TEST_ENRICHMENT_KEY);
+ $enrichmentKey->store();
+ }
+
+ public function tearDown(): void
+ {
+ $enrichmentKey = EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY);
+ if ($enrichmentKey !== null) {
+ $enrichmentKey->delete();
+ }
+
+ parent::tearDown();
+ }
+
+ public function testRenameEnrichment()
+ {
+ $newKey = 'newEnrichmentKey';
+
+ $this->assertNull(EnrichmentKey::fetchByName($newKey));
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_NEW_KEY => $newKey,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+
+ $enrichmentKey = EnrichmentKey::fetchByName($newKey);
+ $this->assertNotNull($enrichmentKey);
+ $enrichmentKey->delete();
+
+ $output = $this->tester->getDisplay();
+
+ $oldKey = self::TEST_ENRICHMENT_KEY;
+
+ $this->assertStringContainsString("Renaming key \"$oldKey\" to \"{$newKey}\"", $output);
+ $this->assertStringContainsString("Renaming translations for enrichment key \"{$newKey}\"", $output);
+ }
+
+ public function testMissingArguments()
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Not enough arguments (missing: "key, newKey")');
+
+ $this->tester->execute([]);
+ }
+
+ public function testArgumentKeyIsUnknown()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_KEY => 'unknownEnrichmentKey',
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_NEW_KEY => 'newEnrichmentKey',
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key "unknownEnrichmentKey" not found', $output);
+ }
+
+ public function testArgumentNewKeyMissing()
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('Not enough arguments (missing: "newKey")');
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ ]);
+ }
+
+ public function testNewKeyAlreadyExists()
+ {
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_NEW_KEY => 'Country',
+ ]);
+
+ $output = $this->tester->getDisplay();
+
+ $this->assertStringContainsString('Enrichment key "Country" already exists', $output);
+ }
+
+ public function testTranslationsAreRenamed()
+ {
+ $newKey = 'newEnrichmentKey';
+
+ $this->assertNull(EnrichmentKey::fetchByName($newKey));
+
+ $helper = new Admin_Model_EnrichmentKeys();
+ $helper->createTranslations(self::TEST_ENRICHMENT_KEY);
+
+ $helper->removeTranslations($newKey); // just in case
+ $this->assertCount(0, $helper->getTranslations($newKey));
+
+ $this->tester->execute([
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_KEY => self::TEST_ENRICHMENT_KEY,
+ Application_Console_Model_EnrichmentRenameCommand::ARGUMENT_NEW_KEY => $newKey,
+ ]);
+
+ $this->assertNull(EnrichmentKey::fetchByName(self::TEST_ENRICHMENT_KEY));
+
+ $enrichmentKey = EnrichmentKey::fetchByName($newKey);
+ $this->assertNotNull($enrichmentKey);
+ $enrichmentKey->delete();
+
+ $this->assertGreaterThan(1, count($helper->getTranslations($newKey)));
+ $this->assertCount(0, $helper->getTranslations(self::TEST_ENRICHMENT_KEY));
+ }
+}
diff --git a/tests/modules/admin/models/EnrichmentKeysTest.php b/tests/modules/admin/models/EnrichmentKeysTest.php
index 1e9692fae..ebc819e2e 100644
--- a/tests/modules/admin/models/EnrichmentKeysTest.php
+++ b/tests/modules/admin/models/EnrichmentKeysTest.php
@@ -29,6 +29,8 @@
* @license http://www.gnu.org/licenses/gpl.html General Public License
*/
+use Opus\Common\EnrichmentKey;
+use Opus\Enrichment\RegexType;
use Opus\Translate\Dao;
class Admin_Model_EnrichmentKeysTest extends ControllerTestCase
@@ -226,4 +228,64 @@ public function testRemoveTranslations()
$translations = $database->getTranslations('default');
$this->assertCount(0, $translations);
}
+
+ public function testGetTranslation()
+ {
+ $model = new Admin_Model_EnrichmentKeys();
+
+ $key = 'MyTestEnrichment';
+
+ $model->createTranslations($key);
+
+ $translations = $model->getTranslations($key);
+
+ $model->removeTranslations($key);
+
+ $this->assertCount(6, $translations);
+
+ $translationKeys = $model->getSupportedKeys();
+
+ foreach ($translationKeys as $translationKey) {
+ $this->assertArrayHasKey($translationKey, $translations);
+ $this->assertEquals('MyTestEnrichment', $translations[$translationKey]['de']);
+ $this->assertEquals('MyTestEnrichment', $translations[$translationKey]['en']);
+ }
+ }
+
+ public function testGetEnrichmentConfig()
+ {
+ $model = new Admin_Model_EnrichmentKeys();
+
+ $key = 'MyTestEnrichment';
+
+ $enrichment = EnrichmentKey::fetchByName($key);
+
+ if ($enrichment === null) {
+ $enrichment = EnrichmentKey::new();
+ $enrichment->setName($key);
+ $enrichment->setType('RegexType');
+ $enrichmentType = new RegexType();
+ $enrichmentType->setRegex('/[a-z]+/');
+ $enrichment->setOptions($enrichmentType->getOptions());
+ $enrichment->store();
+ }
+
+ $this->addModelToCleanup($enrichment);
+
+ $model->createTranslations($key);
+
+ $config = $model->getEnrichmentConfig($key);
+
+ // cleanup
+ $model->removeTranslations($key);
+
+ $this->assertArrayHasKey('name', $config);
+ $this->assertEquals($key, $config['name']);
+ $this->assertArrayHasKey('translations', $config);
+ $this->assertCount(6, $config['translations']);
+
+ $this->assertArrayHasKey('options', $config);
+ $this->assertEquals('none', $config['options']['validation']);
+ $this->assertEquals('/[a-z]+/', $config['options']['regex']);
+ }
}
diff --git a/tests/resources/enrichments/conferenceType.yml b/tests/resources/enrichments/conferenceType.yml
new file mode 100644
index 000000000..d519d7f93
--- /dev/null
+++ b/tests/resources/enrichments/conferenceType.yml
@@ -0,0 +1,18 @@
+# Enrichment configuration for conference types
+name: conferenceType
+
+type: Select
+
+translations:
+ label:
+ de: Art der Konferenzveröffentlichung
+ en: Conference Type
+
+options:
+ validation: strict
+ values:
+ - Konferenzband
+ - Konferenzartikel
+ - Konferenz-Poster
+ - Konferenz-Abstract
+ - Sonstiges
diff --git a/tests/resources/enrichments/doi-import.yml b/tests/resources/enrichments/doi-import.yml
new file mode 100644
index 000000000..3b009c23e
--- /dev/null
+++ b/tests/resources/enrichments/doi-import.yml
@@ -0,0 +1,10 @@
+# Enrichment keys for Publish module DOI import (for OPUS 4.8.0)
+enrichments:
+ - name: opus_import_data
+ - name: local_crossrefDocumentType
+ - name: local_crossrefLicence
+ - name: local_doiImportPopulated
+ - name: local_import_origin
+ - name: opus_doi_flag
+ - name: conference_place
+ - name: conference_title
diff --git a/tests/resources/enrichments/import.yml b/tests/resources/enrichments/import.yml
new file mode 100644
index 000000000..90b19a7b1
--- /dev/null
+++ b/tests/resources/enrichments/import.yml
@@ -0,0 +1,6 @@
+# Example of configuration for multiple enrichments
+enrichments:
+ - name: opus.import.checksum
+ - name: opus.import.date
+ - name: opus.import.file
+ - name: opus.import.user
diff --git a/tests/resources/enrichments/multipleKeys.yml b/tests/resources/enrichments/multipleKeys.yml
new file mode 100644
index 000000000..172e64ed9
--- /dev/null
+++ b/tests/resources/enrichments/multipleKeys.yml
@@ -0,0 +1,6 @@
+# Example of configuration for multiple enrichments
+enrichments:
+ - name: testKey1
+ - name: testKey2
+ - name: testKey3
+ - name: testKey4
diff --git a/tests/resources/enrichments/simpleOption.yml b/tests/resources/enrichments/simpleOption.yml
new file mode 100644
index 000000000..be975bb76
--- /dev/null
+++ b/tests/resources/enrichments/simpleOption.yml
@@ -0,0 +1,17 @@
+# Example of SELECT enrichment with simple options
+# with 'validation: none' - 'none' meaning invalid stored values are allowed to remain
+name: conferenceType
+
+type: Select
+
+translations:
+ label:
+ de: Art der Konferenzveröffentlichung
+ en: Conference Type
+
+options: |
+ Konferenzband
+ Konferenzartikel
+ Konferenz-Poster
+ Konferenz-Abstract
+ Sonstiges
diff --git a/tests/resources/enrichments/singleKey.yml b/tests/resources/enrichments/singleKey.yml
new file mode 100644
index 000000000..f2909f46f
--- /dev/null
+++ b/tests/resources/enrichments/singleKey.yml
@@ -0,0 +1 @@
+name: singleEnrichmentKey