feat: lineup element on TYPO3 13

Restored from a46918d, TCA ported to TYPO3 13; markup matches TYPO3 10.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
frommeandClaude Opus 5.5 committed 2026-10-24 12:29:07 +02:00
1 parent a042eff41d
commit ad4089ae16
4 files changed
+357

No files matched your search

@@ -0,0 +1,52 @@
<?php
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
defined('TYPO3') or die();
call_user_func(function() {
$frontendLanguageFilePrefix = 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:';
ExtensionManagementUtility::addTcaSelectItem(
'tt_content',
'CType',
[
'label' => 'Lineup',
'value' => 'lineup',
'icon' => 'content-image'
],
'gmap',
'after'
);
$GLOBALS['TCA']['tt_content']['columns']['tx_eptheme_lineup'] = [
'exclude' => 0,
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup.items',
'config' => [
'type' => 'inline',
'foreign_table' => 'tx_eptheme_domain_model_lineup',
'foreign_field' => 'tt_content',
'foreign_sortby' => 'sorting',
'maxitems' => 99,
'appearance' => [
'useSortable' => 1,
'collapseAll' => 1,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => 0,
'showPossibleLocalizationRecords' => 0,
'showAllLocalizationLink' => 0
],
],
];
$GLOBALS['TCA']['tt_content']['types']['lineup'] = [
'showitem' => '
--palette--;' . $frontendLanguageFilePrefix . 'palette.general;general,
tx_eptheme_lineup,
--div--;' . $frontendLanguageFilePrefix . 'tabs.access,
hidden;' . $frontendLanguageFilePrefix . 'field.default.hidden,
--div--;' . $frontendLanguageFilePrefix . 'tabs.extended
',
];
});
@@ -0,0 +1,210 @@
<?php
use TYPO3\CMS\Core\Resource\FileType;
return [
'ctrl' => [
'title' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup',
'default_sortby' => 'ORDER BY name',
'label' => 'name',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'dividers2tabs' => true,
'versioningWS' => true,
'hideTable' => true,
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'delete' => 'deleted',
'enablecolumns' => [
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'headline,subline',
'iconfile' => 'EXT:ep_theme/Resources/Public/images/icon_ce.svg',
],
'types' => [
'1' => [
'showitem' => 'hidden, name, description, image, --palette--;;social',
],
],
'palettes' => [
'social' => ['showitem' => 'facebook_url, twitter_url, youtube_url, instagram_url, soundcloud_url'],
],
'columns' => [
'sys_language_uid' => [
'exclude' => 0,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.language',
'config' => ['type' => 'language'],
],
'l10n_parent' => [
'displayCond' => 'FIELD:sys_language_uid:>:0',
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'items' => [
['label' => '', 'value' => 0],
],
'foreign_table' => 'tx_eptheme_domain_model_lineup',
'foreign_table_where' => 'AND tx_eptheme_domain_model_lineup.pid=###CURRENT_PID### AND tx_eptheme_domain_model_lineup.sys_language_uid IN (-1,0)',
],
],
'l10n_diffsource' => [
'config' => [
'type' => 'passthrough',
],
],
't3ver_label' => [
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.versionLabel',
'config' => [
'type' => 'input',
'size' => 30,
'max' => 255,
]
],
'hidden' => [
'exclude' => 0,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.hidden',
'config' => [
'type' => 'check',
],
],
'starttime' => [
'exclude' => 0,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [
'type' => 'datetime',
'size' => 13,
'checkbox' => 0,
'default' => 0,
'behaviour' => [
'allowLanguageSynchronization' => true,
],
],
],
'endtime' => [
'exclude' => 0,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [
'type' => 'datetime',
'size' => 13,
'checkbox' => 0,
'default' => 0,
'behaviour' => [
'allowLanguageSynchronization' => true,
],
],
],
'sorting' => [
'config' => [
'type' => 'passthrough'
],
],
'name' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup.name',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim,required'
],
],
'description' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang.xlf:tx_eptheme_domain_model_lineup.description',
'config' => [
'type' => 'text',
'cols' => 40,
'rows' => 10,
'eval' => 'trim',
'enableRichtext' => true,
],
],
'image' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup.image',
'config' => [
'type' => 'file',
'allowed' => 'common-image-types',
'appearance' => [
'createNewRelationLinkTitle' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference',
'useSortable' => false,
],
'overrideChildTca' => [
'types' => [
FileType::IMAGE->value => [
'showitem' => '
--palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,
--palette--;;filePalette',
],
],
],
'maxitems' => 1
],
],
'facebook_url' => [
'exclude' => 0,
'label' => 'Facebook URL',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
'twitter_url' => [
'exclude' => 0,
'label' => 'Twitter URL',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
'instagram_url' => [
'exclude' => 0,
'label' => 'Instagram URL',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
'youtube_url' => [
'exclude' => 0,
'label' => 'YouTube URL',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
'soundcloud_url' => [
'exclude' => 0,
'label' => 'Soundcloud URL',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim'
],
],
'tt_content' => [
'exclude' => 0,
'label' => 'LLL:EXT:ep_theme/Resources/Private/Language/locallang_db.xlf:tx_eptheme_domain_model_lineup.tt_content',
'config' => [
'type' => 'select',
'default' => 0,
'renderType' => 'selectSingle',
'foreign_table' => 'tt_content',
'minitems' => 0,
'maxitems' => 1,
],
],
],
];
@@ -0,0 +1,24 @@
tt_content.lineup =< lib.contentElement
tt_content.lineup {
templateName = Lineup
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
table = tx_eptheme_domain_model_lineup
where.data = field:uid
where.wrap = tt_content=|
orderBy = sorting
as = items
dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\FilesProcessor
10 {
references.fieldName = image
references.table = tx_eptheme_domain_model_lineup
as = image
}
}
}
}
}
@@ -0,0 +1,71 @@
<html data-namespace-typo3-fluid="true" lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://typo3.org/ns/fluid/ViewHelpers"
xmlns:ep="http://typo3.org/ns/EP/EpTheme/ViewHelpers">
<f:layout name="Default" />
<f:section name="Main">
<div class="max-w-screen-xl mx-auto">
<f:for each="{items}" as="item" iteration="iteration">
<div class="lg:flex odd:flex-row-reverse justify-between items-end mb-16">
<div class="mb-4 lg:mb-0 lg:w-1/2">
<f:image image="{item.image.0}"
loading="lazy"
class="block w-full h-auto"
width="768"
alt="{item.data.name}"/>
</div>
<div class="lg:w-1/2">
<div class="px-4 {f:if(condition: iteration.isEven, then: 'lg:pl-12', else: 'lg:pr-12')}">
<span class="headline headline--secondary headline--underlined">
{item.data.name -> f:format.raw()}
</span>
<div data-rte-content>
{item.data.description -> f:format.html()}
</div>
<div class="flex items-center space-x-6">
<f:if condition="{item.data.facebook_url}">
<a href="{item.data.facebook_url}" target="_blank" title="{item.data.name} bei Facebook">
<svg class="w-8 h-8 {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', suz: \'text-suz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-facebook"></use>
</svg>
</a>
</f:if>
<f:if condition="{item.data.twitter_url}">
<a href="{item.data.twitter_url}" target="_blank" title="{item.data.name} bei Twitter">
<svg class="w-8 h-8 {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', suz: \'text-suz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-twitter"></use>
</svg>
</a>
</f:if>
<f:if condition="{item.data.instagram_url}">
<a href="{item.data.instagram_url}" target="_blank" title="{item.data.name} bei Instagram">
<svg class="w-8 h-8 {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', suz: \'text-suz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-instagram"></use>
</svg>
</a>
</f:if>
<f:if condition="{item.data.youtube_url}">
<a href="{item.data.youtube_url}" target="_blank" title="{item.data.name} bei YouTube">
<svg class="w-8 h-8 {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', suz: \'text-suz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-youtube"></use>
</svg>
</a>
</f:if>
<f:if condition="{item.data.soundcloud_url}">
<a href="{item.data.soundcloud_url}" target="_blank" title="{item.data.name} bei Soundcloud">
<svg class="w-8 h-8 {ep:themeClasses(classes: '{sbw: \'text-sbw-primary\', snz: \'text-snz-primary\', suz: \'text-suz-primary\', uch: \'text-uch-primary\'}', key: settings.themekey)}">
<use href="{f:uri.image(src: 'EXT:ep_theme/Resources/Public/images/icons_sprite.svg')}#icon-soundcloud"></use>
</svg>
</a>
</f:if>
</div>
</div>
</div>
</div>
</f:for>
</div>
</f:section>
</html>