Files
VITEC-website/packages/vitec/Configuration/TCA/tx_vitec_domain_model_solution.php
Oliver Rasche 48da8bccd8 Solution detail page and a single LinkResolver
Closes two annex items that turned out to be the same defect seen from two
sides: markets could link to a detail page, solutions could not, and the code
that turns a page uid into a URL existed four times over.

detail_page for Solution (B-11)
- ext_tables.sql, TCA (group on pages, maxitems 1, in showitem behind slug)
  and Domain\Model\Solution mirror the Market field exactly
- SolutionShowJsonRenderer emits detailUrl
- ModelcardJsonRenderer serialized no detailUrl at all: its shared
  market|solution branch never carried the field. Market modelcards therefore
  gain a link here too, not just solutions.

Service\LinkResolver (B-12)
- one implementation replaces four private copies (Market list/show, Usecase
  list/show). The copies had drifted: Market returned null on failure, Usecase
  an empty string. The contract is now explicit -- null means "no link".
- Usecase keeps a thin resolvePageUrl() wrapper appending ?? '', because it
  concatenates paths and a null would tear the strings apart.
- LocationsJsonRenderer and NewsJsonRenderer stay out on purpose: they resolve
  a full parameter construct resp. slug paths plus canonical, which is not
  page-uid-to-URL and does not fit the same contract.

Requires on the server, the column exists in code only:
    vendor/bin/typo3 database:updateschema "*.add,*.change"
    vendor/bin/typo3 cache:flush
2026-08-10 15:27:16 +02:00

238 lines
9.0 KiB
PHP

<?php
return [
'ctrl' => [
'title' => 'VITEC Solution',
'label' => 'title',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'versioningWS' => true,
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'delete' => 'deleted',
'enablecolumns' => [
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
],
'searchFields' => 'title,subtitle,teaser',
'iconfile' => 'EXT:vitec/Resources/Public/Icons/tx_vitec_domain_model_solution.gif',
'security' => [
'ignorePageTypeRestriction' => true,
],
],
'types' => [
'1' => [
'showitem' => 'title, slug, detail_page, subtitle, teaser, description, image,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:language, sys_language_uid, l10n_parent, l10n_diffsource,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden, starttime, endtime',
],
],
'columns' => [
'sys_language_uid' => [
'exclude' => true,
'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',
'renderType' => 'selectSingle',
'default' => 0,
'items' => [
['', 0],
],
'foreign_table' => 'tx_vitec_domain_model_solution',
'foreign_table_where' => 'AND {#tx_vitec_domain_model_solution}.{#pid}=###CURRENT_PID### AND {#tx_vitec_domain_model_solution}.{#sys_language_uid} IN (-1,0)',
],
],
'l10n_diffsource' => [
'config' => [
'type' => 'passthrough',
],
],
'hidden' => [
'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
'config' => [
'type' => 'check',
'renderType' => 'checkboxToggle',
'items' => [
[
0 => '',
1 => '',
'invertStateDisplay' => true,
],
],
],
],
'starttime' => [
'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.starttime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0,
'behaviour' => [
'allowLanguageSynchronization' => true,
],
],
],
'endtime' => [
'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.endtime',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int',
'default' => 0,
'range' => [
'upper' => mktime(0, 0, 0, 1, 1, 2038),
],
'behaviour' => [
'allowLanguageSynchronization' => true,
],
],
],
'title' => [
'exclude' => false,
'label' => 'Title',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim',
'required' => true,
'default' => '',
],
],
'slug' => [
'exclude' => false,
'label' => 'URL Segment',
'config' => [
'type' => 'slug',
'size' => 50,
'generatorOptions' => [
'fields' => ['title'],
'fieldSeparator' => '-',
'replacements' => [
'/' => '',
],
],
'fallbackCharacter' => '-',
'eval' => 'uniqueInPid',
],
],
'detail_page' => [
'exclude' => true,
'label' => 'Detail Page',
'description' => 'Page that presents this solution. Resolved to a URL in the JSON output; leave empty for no link.',
'config' => [
'type' => 'group',
'allowed' => 'pages',
'size' => 1,
'maxitems' => 1,
],
],
'subtitle' => [
'exclude' => true,
'label' => 'Subtitle',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim',
'default' => '',
],
],
'teaser' => [
'exclude' => true,
'label' => 'Short Teaser (optional)',
'config' => [
'type' => 'input',
'size' => 30,
'eval' => 'trim',
'default' => '',
],
],
'description' => [
'exclude' => true,
'label' => 'Description',
'config' => [
'type' => 'text',
'enableRichtext' => true,
'eval' => 'trim',
'default' => '',
],
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]',
],
'categories' => [
'config' => [
'type' => 'category',
],
],
'image' => [
'exclude' => true,
'label' => 'Image',
'config' => [
'type' => 'inline',
'foreign_table' => 'sys_file_reference',
'foreign_field' => 'uid_foreign',
'foreign_sortby' => 'sorting_foreign',
'foreign_table_field' => 'tablenames',
'foreign_match_fields' => [
'fieldname' => 'image',
],
'foreign_label' => 'uid_local',
'foreign_selector' => 'uid_local',
'overrideChildTca' => [
'columns' => [
'crop' => [
'config' => [
'cropVariants' => \Evomedien\Vitec\Tca\CropVariants::firstImage(),
],
],
'uid_local' => [
'config' => [
'appearance' => [
'elementBrowserType' => 'file',
'elementBrowserAllowed' => 'jpg,jpeg,png,gif,webp,svg',
],
],
],
],
'types' => [
'0' => [
'showitem' => '
--palette--;;imageoverlayPalette,
--palette--;;filePalette',
],
],
],
'maxitems' => 1,
'appearance' => [
'headerThumbnail' => [
'field' => 'uid_local',
'width' => '45',
'height' => '45',
],
'enabledControls' => [
'info' => true,
'new' => false,
'dragdrop' => true,
'sort' => false,
'hide' => true,
'delete' => true,
],
'fileUploadAllowed' => true,
],
],
],
],
];