diff --git a/.tools/psalm/baseline.xml b/.tools/psalm/baseline.xml
index 1fc2bbf9a0..4f414fd49c 100644
--- a/.tools/psalm/baseline.xml
+++ b/.tools/psalm/baseline.xml
@@ -1863,9 +1863,6 @@
$ArtSql->getValue('id'), 'startarticle' => '0', 'clang_id' => $clang]]]>
-
-
-
getValue('path')]]>
getValue('path')]]>
diff --git a/.tools/visual-tests/screenshots/system_settings--dark.png b/.tools/visual-tests/screenshots/system_settings--dark.png
index 20b6a16213..fc0d8256c9 100644
Binary files a/.tools/visual-tests/screenshots/system_settings--dark.png and b/.tools/visual-tests/screenshots/system_settings--dark.png differ
diff --git a/.tools/visual-tests/screenshots/system_settings.png b/.tools/visual-tests/screenshots/system_settings.png
index af6193acfd..2dd8800f99 100644
Binary files a/.tools/visual-tests/screenshots/system_settings.png and b/.tools/visual-tests/screenshots/system_settings.png differ
diff --git a/.tools/visual-tests/screenshots/system_settings_safemode--dark.png b/.tools/visual-tests/screenshots/system_settings_safemode--dark.png
index 0e419a2170..a932888869 100644
Binary files a/.tools/visual-tests/screenshots/system_settings_safemode--dark.png and b/.tools/visual-tests/screenshots/system_settings_safemode--dark.png differ
diff --git a/.tools/visual-tests/screenshots/system_settings_safemode.png b/.tools/visual-tests/screenshots/system_settings_safemode.png
index c77af2f784..76c9b352ba 100644
Binary files a/.tools/visual-tests/screenshots/system_settings_safemode.png and b/.tools/visual-tests/screenshots/system_settings_safemode.png differ
diff --git a/lang/de_de.lang b/lang/de_de.lang
index 01a675cfa6..a8f7f3926d 100644
--- a/lang/de_de.lang
+++ b/lang/de_de.lang
@@ -1302,10 +1302,8 @@ perm_options_linkmap[all_categories] = Alle Kategorien in der Linkmap anzeigen
system_setting_start_article_id = Startartikel
system_setting_notfound_article_id = Fehlerartikel
-system_setting_default_template = Standardtemplate
system_setting_start_article_id_invalid = Ungültiger Startartikel!
system_setting_notfound_article_id_invalid = Ungültiger Fehlerartikel!
-system_setting_default_template_invalid = Ungültiges Standardtemplate!
linkmap = Linkmap
linkmap_categories = Kategorien
diff --git a/lang/en_gb.lang b/lang/en_gb.lang
index a63dc2bf81..a3e398f2a0 100644
--- a/lang/en_gb.lang
+++ b/lang/en_gb.lang
@@ -1265,10 +1265,8 @@ perm_options_linkmap[all_categories] = Show all categories in Linkmap
system_setting_start_article_id = Start article
system_setting_notfound_article_id = Not-found article
-system_setting_default_template = Default template
system_setting_start_article_id_invalid = Invalid start article!
system_setting_notfound_article_id_invalid = Invalid not-found article!
-system_setting_default_template_invalid = Invalid default template!
linkmap = Linkmap
linkmap_categories = Categories
diff --git a/pages/system/settings.php b/pages/system/settings.php
index b4dda1c477..d3e3f59f0a 100644
--- a/pages/system/settings.php
+++ b/pages/system/settings.php
@@ -2,7 +2,6 @@
use Redaxo\Core\Cache;
use Redaxo\Core\Content\Article;
-use Redaxo\Core\Content\Template;
use Redaxo\Core\Core;
use Redaxo\Core\Database\Sql;
use Redaxo\Core\Exception\InvalidArgumentException;
@@ -108,14 +107,6 @@
Core::setConfig($key, $value);
break;
- case 'default_template':
- $value = (string) $value;
- if ('' !== $value && !Template::exists($value)) {
- $error[] = I18n::msg('system_setting_default_template_invalid');
- }
- Core::setConfig('default_template', '' !== $value ? $value : null);
- break;
-
case 'article_history':
case 'article_work_version':
$value = (bool) $value;
@@ -338,27 +329,6 @@
$field->setValue(Core::getConfig('notfound_article_id', 1));
$content .= $field->get();
-$field = new SelectField();
-$field->setAttribute('class', 'form-control selectpicker');
-$field->setAttribute('name', 'settings[default_template]');
-$field->setLabel(I18n::msg('system_setting_default_template'));
-$select = $field->getSelect();
-$select->setSize(1);
-$defaultTemplate = Template::getDefaultKey();
-if (null !== $defaultTemplate) {
- $select->setSelected($defaultTemplate);
-}
-
-$templates = Template::getTemplatesForCategory(0);
-if (empty($templates)) {
- $select->addOption(I18n::msg('option_no_template'), '');
-} else {
- foreach ($templates as $key => $template) {
- $select->addOption(I18n::translate($template->name), $key);
- }
-}
-$content .= $field->get();
-
$field = new SelectField();
$field->setAttribute('class', 'form-control selectpicker');
$field->setAttribute('name', 'settings[article_history]');
diff --git a/src/Content/CategoryHandler.php b/src/Content/CategoryHandler.php
index aa9281e361..2f7ee93eac 100644
--- a/src/Content/CategoryHandler.php
+++ b/src/Content/CategoryHandler.php
@@ -66,7 +66,10 @@ public static function addCategory($categoryId, array $data)
// $sql->setDebug();
$sql->setQuery('select clang_id,template from ' . Core::getTablePrefix() . 'article where id=? and startarticle=1', [$categoryId]);
for ($i = 0; $i < $sql->getRows(); $i++, $sql->next()) {
- $startpageTemplates[(int) $sql->getValue('clang_id')] = $sql->getValue('template');
+ $template = (string) $sql->getValue('template');
+ if ('' !== $template) {
+ $startpageTemplates[(int) $sql->getValue('clang_id')] = $template;
+ }
}
}
@@ -78,15 +81,12 @@ public static function addCategory($categoryId, array $data)
// Kategorie in allen Sprachen anlegen
$AART = Sql::factory();
foreach (Language::getAllIds() as $key) {
- $templateKey = Template::getDefaultKey();
- if (isset($startpageTemplates[$key]) && '' != $startpageTemplates[$key]) {
- $templateKey = $startpageTemplates[$key];
- }
+ // Inherit the template from the start article of the respective language, otherwise use the default
+ $templateKey = $startpageTemplates[$key] ?? Template::getDefaultKey();
- // Wenn Template nicht vorhanden, dann entweder erlaubtes nehmen
- // oder leer setzen.
+ // Fall back to the first allowed template if the chosen one is not available in this category
if (null === $templateKey || !isset($templates[$templateKey])) {
- $templateKey = count($templates) > 0 ? key($templates) : null;
+ $templateKey = array_key_first($templates);
}
$AART->setTable(Core::getTablePrefix() . 'article');
diff --git a/src/Content/Template.php b/src/Content/Template.php
index 4ed385d8ba..9b51a69672 100644
--- a/src/Content/Template.php
+++ b/src/Content/Template.php
@@ -2,24 +2,54 @@
namespace Redaxo\Core\Content;
+use InvalidArgumentException;
use Redaxo\Core\ClassDiscovery;
-use Redaxo\Core\Core;
-use Redaxo\Core\Util\Type;
+
+use function sprintf;
abstract class Template
{
/** @var array|null */
private static ?array $instances = null;
+ /** @var class-string|null */
+ private static ?string $defaultClass = null;
+
public function __construct(
/** Unique key, used as DB reference in rex_article.template. */
public readonly string $key,
public readonly string $name,
) {}
- public static function getDefaultKey(): ?string
+ /**
+ * Sets the default template, used e.g. for new articles.
+ *
+ * Call this in your project's `boot()` method.
+ *
+ * @param class-string $class
+ */
+ final public static function setDefault(string $class): void
+ {
+ if (null === self::get($class)) {
+ throw new InvalidArgumentException(sprintf('"%s" is not a registered template.', $class));
+ }
+
+ self::$defaultClass = $class;
+ }
+
+ /**
+ * Returns the key of the default template.
+ *
+ * If no default has been set, the first available template is used.
+ * Returns `null` only when no templates exist at all.
+ */
+ final public static function getDefaultKey(): ?string
{
- return Type::nullOrString(Core::getConfig('default_template'));
+ if (null !== self::$defaultClass) {
+ return self::get(self::$defaultClass)?->key;
+ }
+
+ return array_key_first(self::getAll());
}
/**