From bdc8988e2843f5d8515c6d90a29aef35aaebe3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Mummert?= Date: Wed, 4 Nov 2026 16:16:33 +0100 Subject: [PATCH] Always open the event detail page instead of redirecting to the external URL Events with a URL were saved with source "external", so Contao linked lists straight to the external site and redirected the detail page. The URL is now kept in the url field and only shown as a button on the detail page. - frontend form saves source "default" for every event - backend: source option "external" removed, url field relabelled "Externer Link", obsolete target field dropped from the palette - migration switches existing source="external" events to "default" Co-Authored-By: Claude Opus 5.5 --- contao/dca/tl_calendar_events.php | 18 ++++++- contao/languages/de/tl_calendar_events.php | 1 + contao/languages/en/tl_calendar_events.php | 1 + .../ExternalEventSourceMigration.php | 49 +++++++++++++++++++ src/Service/EventRepository.php | 3 +- 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/Migration/ExternalEventSourceMigration.php diff --git a/contao/dca/tl_calendar_events.php b/contao/dca/tl_calendar_events.php index 222d224..29fba6a 100644 --- a/contao/dca/tl_calendar_events.php +++ b/contao/dca/tl_calendar_events.php @@ -6,6 +6,7 @@ use Contao\CoreBundle\DataContainer\PaletteManipulator; use Contao\DataContainer; use Contao\Database; use Contao\StringUtil; +use Contao\System; unset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['location']); unset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['address']); @@ -30,7 +31,7 @@ $GLOBALS['TL_DCA']['tl_calendar_events']['config']['onload_callback'][] = static ->applyToPalette((string) $paletteName, 'tl_calendar_events'); PaletteManipulator::create() - ->addField(['source', 'url', 'target'], 'details_legend', PaletteManipulator::POSITION_APPEND) + ->addField(['source', 'url'], 'details_legend', PaletteManipulator::POSITION_APPEND) ->addField(['termsAccepted', 'isSoldOut', 'isCanceled'], 'publish_legend', PaletteManipulator::POSITION_APPEND) ->applyToPalette((string) $paletteName, 'tl_calendar_events'); } @@ -169,6 +170,20 @@ $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['termsAccepted'] = [ if (isset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source']) && is_array($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source'])) { $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source']['eval'] ??= []; $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source']['eval']['tl_class'] = 'w50'; + + // Keine Weiterleitung auf externe Seiten: Events öffnen immer die Detailseite, + // die externe URL (Feld "url") wird dort als Button ausgegeben. + $originalSourceOptionsCallback = $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source']['options_callback'] ?? null; + + if (null !== $originalSourceOptionsCallback) { + $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['source']['options_callback'] = static function (DataContainer $dc) use ($originalSourceOptionsCallback): array { + $options = \is_array($originalSourceOptionsCallback) + ? System::importStatic($originalSourceOptionsCallback[0])->{$originalSourceOptionsCallback[1]}($dc) + : $originalSourceOptionsCallback($dc); + + return array_values(array_diff((array) $options, ['external'])); + }; + } } if (isset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['target']) && is_array($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['target'])) { @@ -179,6 +194,7 @@ if (isset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['target']) && is_ar if (isset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']) && is_array($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url'])) { $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']['eval'] ??= []; $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']['eval']['tl_class'] = 'clr'; + $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']['label'] = &$GLOBALS['TL_LANG']['tl_calendar_events']['url']; $GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']['eval']['mandatory'] = false; unset($GLOBALS['TL_DCA']['tl_calendar_events']['fields']['url']['eval']['rgxp']); } diff --git a/contao/languages/de/tl_calendar_events.php b/contao/languages/de/tl_calendar_events.php index d92ab52..5ef83c5 100644 --- a/contao/languages/de/tl_calendar_events.php +++ b/contao/languages/de/tl_calendar_events.php @@ -10,3 +10,4 @@ $GLOBALS['TL_LANG']['tl_calendar_events']['photographer'] = ['Urheber/Fotograf', $GLOBALS['TL_LANG']['tl_calendar_events']['isSoldOut'] = ['Ausverkauft', 'Diese Veranstaltung ist ausverkauft.']; $GLOBALS['TL_LANG']['tl_calendar_events']['isCanceled'] = ['Abgesagt', 'Diese Veranstaltung wurde abgesagt.']; $GLOBALS['TL_LANG']['tl_calendar_events']['termsAccepted'] = ['Nutzungsbedingungen akzeptiert', 'Die Nutzungsbedingungen wurden akzeptiert.']; +$GLOBALS['TL_LANG']['tl_calendar_events']['url'] = ['Externer Link', 'Weiterführende Seite zur Veranstaltung (z. B. Website des Veranstalters). Wird auf der Detailseite als Button ausgegeben; Listen verlinken immer auf die Detailseite.']; diff --git a/contao/languages/en/tl_calendar_events.php b/contao/languages/en/tl_calendar_events.php index 61f0a11..9073260 100644 --- a/contao/languages/en/tl_calendar_events.php +++ b/contao/languages/en/tl_calendar_events.php @@ -10,3 +10,4 @@ $GLOBALS['TL_LANG']['tl_calendar_events']['photographer'] = ['Author/Photographe $GLOBALS['TL_LANG']['tl_calendar_events']['isSoldOut'] = ['Sold out', 'This event is sold out.']; $GLOBALS['TL_LANG']['tl_calendar_events']['isCanceled'] = ['Canceled', 'This event has been canceled.']; $GLOBALS['TL_LANG']['tl_calendar_events']['termsAccepted'] = ['Terms accepted', 'The terms of use have been accepted.']; +$GLOBALS['TL_LANG']['tl_calendar_events']['url'] = ['External link', 'Further page about the event (e.g. organiser website). Shown as a button on the event detail page; lists always link to the detail page.']; diff --git a/src/Migration/ExternalEventSourceMigration.php b/src/Migration/ExternalEventSourceMigration.php new file mode 100644 index 0000000..851080c --- /dev/null +++ b/src/Migration/ExternalEventSourceMigration.php @@ -0,0 +1,49 @@ +connection->createSchemaManager(); + + if (!$schemaManager->tablesExist(['tl_calendar_events'])) { + return false; + } + + return (int) $this->connection->fetchOne( + "SELECT COUNT(*) FROM tl_calendar_events WHERE source = 'external'", + ) > 0; + } + + public function run(): MigrationResult + { + $count = $this->connection->executeStatement( + "UPDATE tl_calendar_events SET source = 'default' WHERE source = 'external'", + ); + + return $this->createResult(true, sprintf('%d Events von externer Weiterleitung auf Detailseite umgestellt.', $count)); + } +} diff --git a/src/Service/EventRepository.php b/src/Service/EventRepository.php index 45d8f30..90f8abf 100644 --- a/src/Service/EventRepository.php +++ b/src/Service/EventRepository.php @@ -651,7 +651,8 @@ class EventRepository 'teaser' => $data['teaser'] ?? null, 'description' => $data['description'] ?? null, 'url' => $url, - 'source' => '' !== $url ? 'external' : 'default', + // Externe URL wird nur als Link-Button auf der Detailseite ausgegeben, Listen verlinken immer auf die Detailseite + 'source' => 'default', 'photographer' => $data['photographer'] ?? '', 'addImage' => !empty($data['addImage']) ? 1 : 0, 'termsAccepted' => !empty($data['termsAccepted']) ? '1' : '',