Product text import from agency XLSX workbooks

VITEC Import module: Products tab is now a searchable/sortable product
overview. "Edit Product" opens an XLSX upload with per-field source
mapping (component + cell), old/new preview and checkbox apply via
DataHandler; the mapping and manual matches are persisted and preselect
the next workbook. Category workbooks are detected and rejected.

- new: ProductXlsxReader (PhpSpreadsheet), ProductTextImportController,
  Products/ProductTexts templates, 4 module routes
- related products: per-pair card text in new side table
  tx_vitec_product_related_text (survives MM rewrites), emitted as
  `cardtext` in the product JSON; missing MM relations added add-only
- card copy read from Body Copy (D) with fallback to CTA/Card Copy (E) -
  the workbooks fill either depending on row type
- product detail page <title> now uses seotitle with title fallback
  (provider made singleton and fed from the JSON renderer)
- per-user recent-search badges; last loaded workbook stored per product
  (tx_vitec_product_workbook), Edit Product reopens on it
- composer: add phpoffice/phpspreadsheet ^5.9
- diagnostics: migrations/check_workbook.php
This commit is contained in:
orasche committed 2026-08-21 11:00:45 +02:00
1 parent 12eb40614b
commit 7bd1161abf
28 files changed
+2594 -39

No files matched your search

@@ -23,12 +23,12 @@ return [
],
],
'types' => [
'1' => ['showitem' => 'title, subtitle, slug, teaser, description, applications, highlights, contentelement, contentelementcta, downloads, showdatapath,
'1' => ['showitem' => 'title, subtitle, slug, teaser, description, description2, applications, capabilities, highlights, contentelement, contentelementcta, downloads, portfolio, showdatapath, textrelatedproducts, relatedprodukt,
--div--;SEO, seotitle, urltitle, seometa, keywords, structureddata,
--div--;Images and Videos, productimage, ogimage, video, videofile,
--div--;Images and Videos, heroimage, productimage, ogimage, video, videofile,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:categories, categories,
--div--;Visibility, hideonapp, hideonwebsite, hideondatasheets, hideonproducts, shortcut, shortcutpid,
--div--;Misc, legacy, supportproduct, subproduct, relatedprodukt,
--div--;Misc, legacy, supportproduct, subproduct,
--div--;LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf:access, hidden, starttime, endtime'],
],
'columns' => [
@@ -556,6 +556,88 @@ return [
],
],
'description2' => [
'exclude' => true,
'label' => '2nd Description',
'config' => [
'type' => 'text',
'enableRichtext' => true,
'eval' => 'trim',
'default' => ''
],
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
],
'capabilities' => [
'exclude' => true,
'label' => 'Capabilities',
'config' => [
'type' => 'text',
'enableRichtext' => true,
'eval' => 'trim',
'default' => ''
],
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
],
'portfolio' => [
'exclude' => true,
'label' => 'Portfolio',
'description' => 'Link to the product portfolio (page, file or external URL)',
'config' => [
'type' => 'link',
'allowedTypes' => ['page', 'url', 'file', 'record'],
'size' => 50,
],
],
'textrelatedproducts' => [
'exclude' => true,
'label' => 'Text Related Products',
'config' => [
'type' => 'text',
'enableRichtext' => true,
'eval' => 'trim',
'default' => ''
],
'defaultExtras' => 'richtext:rte_transform[mode=ts_css]'
],
'heroimage' => [
'exclude' => true,
'label' => 'Hero Image(s)',
'config' => [
'type' => 'inline',
'foreign_table' => 'sys_file_reference',
'foreign_field' => 'uid_foreign',
'foreign_sortby' => 'sorting_foreign',
'foreign_table_field' => 'tablenames',
'foreign_match_fields' => [
'fieldname' => 'heroimage',
],
'appearance' => [
'collapseAll' => true,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => true,
'showPossibleLocalizationRecords' => true,
'showAllLocalizationLink' => true,
],
'behaviour' => [
'allowLanguageSynchronization' => true,
],
'filter' => [
[
'userFunc' => \TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter::class . '->filterInlineChildren',
'parameters' => [
'allowedFileExtensions' => 'jpg,jpeg,png,gif,webp',
],
],
],
'maxitems' => 10,
'minitems' => 0,
],
],
'contentelement' => [
'exclude' => true,
'label' => 'Select Content Element for Key Features Section',