From 51a92ea45e51c54ca826be6770535f1879b1d569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Mummert?= Date: Thu, 26 Feb 2026 22:00:12 +0100 Subject: [PATCH] Map tags: load live organization tags and sanitize selections --- contao/dca/tl_module.php | 46 +++++++++++++++++-- .../Frontend/EventMapController.php | 8 ++++ src/Service/MapModuleDataProvider.php | 11 +++-- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/contao/dca/tl_module.php b/contao/dca/tl_module.php index f06f528..76d07ef 100644 --- a/contao/dca/tl_module.php +++ b/contao/dca/tl_module.php @@ -74,15 +74,33 @@ $GLOBALS['TL_DCA']['tl_module']['fields']['organizationTypeTags'] = [ 'exclude' => true, 'inputType' => 'checkbox', 'options_callback' => static function () { + $database = Database::getInstance(); + $labelExpression = $database->fieldExists('title', 'tl_tags') + ? "COALESCE(NULLIF(t.title, ''), t.tag)" + : 't.tag'; + $rows = Database::getInstance() - ->prepare('SELECT DISTINCT t.id, t.tag FROM tl_tags t LEFT JOIN tl_tags_rel r ON r.tag_id=t.id AND r.ptable=? AND r.field=? ORDER BY t.tag ASC') + ->prepare(sprintf( + 'SELECT DISTINCT t.id, %1$s AS label + FROM tl_tags_rel r + INNER JOIN tl_tags t ON t.id=r.tag_id + WHERE r.ptable=? AND r.field=? + ORDER BY label ASC', + $labelExpression, + )) ->execute('tl_organization', 'tags') ->fetchAllAssoc(); $options = []; foreach ($rows as $row) { - $options[(int) $row['id']] = (string) $row['tag']; + $label = trim((string) ($row['label'] ?? '')); + + if ('' === $label) { + continue; + } + + $options[(int) $row['id']] = $label; } return $options; @@ -204,15 +222,33 @@ $GLOBALS['TL_DCA']['tl_module']['fields']['mapInitialOrganizationTagId'] = [ 'exclude' => true, 'inputType' => 'select', 'options_callback' => static function (): array { - $rows = Database::getInstance() - ->prepare('SELECT DISTINCT t.id, t.tag FROM tl_tags t LEFT JOIN tl_tags_rel r ON r.tag_id=t.id AND r.ptable=? AND r.field=? ORDER BY t.tag ASC') + $database = Database::getInstance(); + $labelExpression = $database->fieldExists('title', 'tl_tags') + ? "COALESCE(NULLIF(t.title, ''), t.tag)" + : 't.tag'; + + $rows = $database + ->prepare(sprintf( + 'SELECT DISTINCT t.id, %1$s AS label + FROM tl_tags_rel r + INNER JOIN tl_tags t ON t.id=r.tag_id + WHERE r.ptable=? AND r.field=? + ORDER BY label ASC', + $labelExpression, + )) ->execute('tl_organization', 'tags') ->fetchAllAssoc(); $options = []; foreach ($rows as $row) { - $options[(int) $row['id']] = (string) $row['tag']; + $label = trim((string) ($row['label'] ?? '')); + + if ('' === $label) { + continue; + } + + $options[(int) $row['id']] = $label; } return $options; diff --git a/src/Controller/Frontend/EventMapController.php b/src/Controller/Frontend/EventMapController.php index 7f0e1e5..d133a8b 100644 --- a/src/Controller/Frontend/EventMapController.php +++ b/src/Controller/Frontend/EventMapController.php @@ -44,6 +44,14 @@ class EventMapController extends AbstractFrontendModuleController array_map('intval', StringUtil::deserialize($model->organizationTypeTags ?? null, true)), static fn (int $tagId): bool => $tagId > 0, ))); + $availableOrganizationTags = $this->mapModuleDataProvider->getOrganizationTags(); + $availableOrganizationTagIds = array_map( + static fn (array $tag): int => (int) ($tag['id'] ?? 0), + $availableOrganizationTags, + ); + $selectedOrganizationTagIds = [] === $selectedOrganizationTagIds + ? [] + : array_values(array_intersect($selectedOrganizationTagIds, $availableOrganizationTagIds)); $initialDisplay = (string) ($model->mapInitialDisplay ?? self::DEFAULT_INITIAL_DISPLAY); $initialOrganizationTagId = (int) ($model->mapInitialOrganizationTagId ?? 0); $centerMode = (string) ($model->mapCenterMode ?? self::DEFAULT_CENTER_MODE); diff --git a/src/Service/MapModuleDataProvider.php b/src/Service/MapModuleDataProvider.php index 372fb03..5d1d77d 100644 --- a/src/Service/MapModuleDataProvider.php +++ b/src/Service/MapModuleDataProvider.php @@ -150,7 +150,7 @@ class MapModuleDataProvider */ public function getOrganizationTags(array $selectedTagIds = []): array { - if (!$this->tableExists('tl_tags')) { + if (!$this->tableExists('tl_tags') || !$this->tableExists('tl_tags_rel')) { return []; } @@ -168,8 +168,13 @@ class MapModuleDataProvider $qb = $this->connection->createQueryBuilder(); $qb - ->select('t.id', sprintf('t.%s AS label', $labelColumn)) - ->from('tl_tags', 't') + ->select('DISTINCT t.id', sprintf('t.%s AS label', $labelColumn)) + ->from('tl_tags_rel', 'r') + ->innerJoin('r', 'tl_tags', 't', 't.id = r.tag_id') + ->andWhere('r.ptable = :organization_ptable') + ->andWhere('(r.field = :organization_field OR r.field IS NULL OR r.field = \'\')') + ->setParameter('organization_ptable', 'tl_organization') + ->setParameter('organization_field', 'tags') ->orderBy(sprintf('t.%s', $labelColumn), 'ASC'); if ([] !== $selectedTagIds) {