diff --git a/contao/dca/tl_module.php b/contao/dca/tl_module.php index 551edd9..48a80de 100644 --- a/contao/dca/tl_module.php +++ b/contao/dca/tl_module.php @@ -3,6 +3,7 @@ declare(strict_types=1); use Contao\Database; +use Contao\Controller; use Contao\StringUtil; $GLOBALS['TL_DCA']['tl_module']['palettes']['member_organizations'] = '{title_legend},name,headline,type;{eventmanager_legend},editPage;{protected_legend:hide},protected;{expert_legend:hide},guests,cssID'; @@ -157,3 +158,15 @@ $GLOBALS['TL_DCA']['tl_module']['fields']['eventListDomId'] = [ 'eval' => ['includeBlankOption' => true, 'chosen' => true, 'tl_class' => 'w50'], 'sql' => ['type' => 'string', 'length' => 128, 'default' => ''], ]; + +if (isset($GLOBALS['TL_DCA']['tl_module']['fields']['list_layout'])) { + $GLOBALS['TL_DCA']['tl_module']['fields']['list_layout']['options_callback'] = static function (): array { + $options = Controller::getTemplateGroup('list_'); + + if (!isset($options['list_default_organisationen'])) { + $options['list_default_organisationen'] = 'list_default_organisationen'; + } + + return $options; + }; +} diff --git a/src/EventListener/OrganizationListingTemplateDataListener.php b/src/EventListener/OrganizationListingTemplateDataListener.php index 6b8932c..0f66aa1 100644 --- a/src/EventListener/OrganizationListingTemplateDataListener.php +++ b/src/EventListener/OrganizationListingTemplateDataListener.php @@ -32,6 +32,7 @@ class OrganizationListingTemplateDataListener } $rowToOrganizationIdMap = []; + $rowToTitleMap = []; foreach ($tbody as $rowIndex => $row) { if (!\is_array($row)) { @@ -42,6 +43,29 @@ class OrganizationListingTemplateDataListener if ($organizationId > 0) { $rowToOrganizationIdMap[(int) $rowIndex] = $organizationId; + continue; + } + + $title = $this->extractRowFieldContent($row, 'title'); + + if ('' !== $title) { + $rowToTitleMap[(int) $rowIndex] = $this->normalizeTitle($title); + } + } + + if ([] !== $rowToTitleMap) { + $titleToOrganizationIdMap = $this->resolveOrganizationIdsByTitle(array_values(array_unique(array_filter($rowToTitleMap)))); + + foreach ($rowToTitleMap as $rowIndex => $title) { + if (isset($rowToOrganizationIdMap[$rowIndex])) { + continue; + } + + $organizationId = $titleToOrganizationIdMap[$title] ?? 0; + + if ($organizationId > 0) { + $rowToOrganizationIdMap[$rowIndex] = $organizationId; + } } } @@ -151,6 +175,55 @@ class OrganizationListingTemplateDataListener return 0; } + /** @param list $titles + * @return array + */ + private function resolveOrganizationIdsByTitle(array $titles): array + { + if ([] === $titles) { + return []; + } + + $rows = $this->connection->executeQuery( + 'SELECT o.id, o.title FROM tl_organization o WHERE o.title IN (?)', + [$titles], + [ArrayParameterType::STRING], + )->fetchAllAssociative(); + + $titleToIdsMap = []; + + foreach ($rows as $row) { + $organizationId = (int) ($row['id'] ?? 0); + $title = $this->normalizeTitle((string) ($row['title'] ?? '')); + + if ($organizationId <= 0 || '' === $title) { + continue; + } + + $titleToIdsMap[$title][] = $organizationId; + } + + $titleToOrganizationIdMap = []; + + foreach ($titleToIdsMap as $title => $organizationIds) { + $organizationIds = array_values(array_unique(array_map('intval', $organizationIds))); + + if (1 === \count($organizationIds)) { + $titleToOrganizationIdMap[$title] = $organizationIds[0]; + } + } + + return $titleToOrganizationIdMap; + } + + private function normalizeTitle(string $title): string + { + $title = html_entity_decode($title, ENT_QUOTES | ENT_HTML5, 'UTF-8'); + $title = trim(strip_tags($title)); + + return preg_replace('/\s+/u', ' ', $title) ?? ''; + } + /** @param list $organizationIds * @return array, slugs: list}> */ diff --git a/templates/list_default_organisationen.html.twig b/templates/list_default_organisationen.html.twig deleted file mode 100644 index c799534..0000000 --- a/templates/list_default_organisationen.html.twig +++ /dev/null @@ -1,258 +0,0 @@ -{% extends '@Contao/block_searchable.html.twig' %} - -{% set wrapperAttributes = attrs() - .addClass(['ce_table', 'listing']) - .mergeWith(wrapperAttributes|default) -%} - -{% block content %} - - {% set legacyTagLabels = { - '10': 'Sport', - '11': 'Kultur', - '12': 'Politik', - '13': 'Soziales', - '14': 'Freizeit', - '15': 'Bildung', - '16': 'Religion', - '17': 'Natur', - '18': 'Gesellschaft' - } %} - - {% if searchable %} - - {% endif %} - - {% if per_page %} -
-
-
- - - - -
- - -
-
- -
-
-
-
- {% endif %} - - {% if searchable and for and not tbody|default %} - {{ no_results }} - {% else %} - {% set tagOptions = {} %} - - {% for row in tbody|default([]) %} - {% set tagsRaw = row.tag_labels.content|default(row.tags.content|default(''))|striptags %} - {% set tagsPrepared = tagsRaw|replace({' ': '', '&nbsp;': '', ' ': '', ';': ',', '|': ',', '/': ',', ', ': ',', ' ,': ','}) %} - {% set tagParts = tagsPrepared is not empty ? tagsPrepared|split(',') : [] %} - - {% for part in tagParts %} - {% set tagValue = part|striptags|replace({' ': '', '&nbsp;': '', ' ': ''})|trim %} - - {% if legacyTagLabels[tagValue] is defined %} - {% set tagLabel = legacyTagLabels[tagValue] %} - {% elseif tagValue matches '/^\\d+$/' %} - {% set tagLabel = '' %} - {% elseif tagValue matches '/^[\\p{L}\\p{N}\\s._,&+\\-\\/]+$/u' %} - {% set tagLabel = tagValue %} - {% else %} - {% set tagLabel = '' %} - {% endif %} - - {% if tagLabel is not empty %} - {% set tagSlug = tagLabel|lower|replace({'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss', ' ': '-', '/': '-', '&': '-', '+': '-', '.': '', ',': '', '(': '', ')': '', '"': '', "'": ''}) %} - - {% if tagSlug is not empty and tagOptions[tagSlug] is not defined %} - {% set tagOptions = tagOptions|merge({ (tagSlug): tagLabel }) %} - {% endif %} - {% endif %} - {% endfor %} - {% endfor %} - - - -
- - - -
- -
-
- {% for row in tbody|default([]) %} - {% set tagSlugsRaw = row.tag_slugs.content|default('')|trim %} - {% set tagsRaw = row.tag_labels.content|default(row.tags.content|default(''))|striptags %} - {% set tagsPrepared = tagsRaw|replace({' ': '', '&nbsp;': '', ' ': '', ';': ',', '|': ',', '/': ',', ', ': ',', ' ,': ','}) %} - {% set tagParts = tagsPrepared is not empty ? tagsPrepared|split(',') : [] %} - - {% set tagClasses = [] %} - {% set tagSlugs = [] %} - - {% if tagSlugsRaw is not empty %} - {% for slug in tagSlugsRaw|split(',') %} - {% set cleanedSlug = slug|trim %} - - {% if cleanedSlug is not empty %} - {% set tagSlugs = tagSlugs|merge([cleanedSlug]) %} - {% set tagClasses = tagClasses|merge(['tag-' ~ cleanedSlug]) %} - {% endif %} - {% endfor %} - {% endif %} - - {% for part in tagParts if tagSlugsRaw is empty %} - {% set tagValue = part|striptags|replace({' ': '', '&nbsp;': '', ' ': ''})|trim %} - - {% if legacyTagLabels[tagValue] is defined %} - {% set tagLabel = legacyTagLabels[tagValue] %} - {% elseif tagValue matches '/^\\d+$/' %} - {% set tagLabel = '' %} - {% elseif tagValue matches '/^[\\p{L}\\p{N}\\s._,&+\\-\\/]+$/u' %} - {% set tagLabel = tagValue %} - {% else %} - {% set tagLabel = '' %} - {% endif %} - - {% if tagLabel is not empty %} - {% set tagSlug = tagLabel|lower|replace({'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss', ' ': '-', '/': '-', '&': '-', '+': '-', '.': '', ',': '', '(': '', ')': '', '"': '', "'": ''}) %} - - {% if tagSlug is not empty %} - {% set tagClasses = tagClasses|merge(['tag-' ~ tagSlug]) %} - {% set tagSlugs = tagSlugs|merge([tagSlug]) %} - {% endif %} - {% endif %} - {% endfor %} - - {% set title = row.title.content|default('') %} - {% set logoUuid = row.logo_uuid.content|default('')|trim %} - {% set lastCol = row|last %} - -
-
- {% if logoUuid is not empty %} - - {% endif %} - - {% if title is not empty %} -
{{ title|sanitize_html }}
- {% endif %} - - {% if details and lastCol and lastCol.url|default %} - - {% endif %} -
-
- {% endfor %} -
-
- {% endif %} - - {% if pagination is defined %} - {{ pagination|raw }} - {% endif %} - - - - -{% endblock %}