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

+37
View File
@@ -53,6 +53,11 @@ CREATE TABLE tx_vitec_domain_model_product (
contentelementcta varchar(255) DEFAULT '' NOT NULL,
videofile int(11) unsigned DEFAULT '0' NOT NULL,
showdatapath smallint(5) unsigned DEFAULT '0' NOT NULL,
heroimage int(11) unsigned DEFAULT '0' NOT NULL,
description2 text,
capabilities text,
portfolio varchar(1024) DEFAULT '' NOT NULL,
textrelatedproducts text,
KEY parent (pid)
);
CREATE TABLE tx_vitec_domain_model_download (
@@ -311,6 +316,7 @@ CREATE TABLE tx_vitec_import_mapping (
model varchar(64) DEFAULT '' NOT NULL,
identity_field varchar(64) DEFAULT 'slug' NOT NULL,
mapping text,
record_aliases text,
PRIMARY KEY (uid),
KEY model (model)
);
@@ -325,3 +331,34 @@ CREATE TABLE tx_vitec_seo_research (
payload mediumtext,
PRIMARY KEY (uid)
);
--
-- Per-pair card copy for the related-products relation. Deliberately NOT a
-- column on tx_vitec_product_related_mm: DataHandler rewrites the MM rows on
-- every save of the product (delete + reinsert to apply sorting), which would
-- silently wipe any extra column. This side table survives that; orphaned rows
-- (relation later removed) are simply never joined. No TCA on purpose -
-- written by the product-text import module, read by ProductShowJsonRenderer.
--
CREATE TABLE tx_vitec_product_related_text (
product_uid int(11) DEFAULT '0' NOT NULL,
related_uid int(11) DEFAULT '0' NOT NULL,
cardtext text,
tstamp int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (product_uid, related_uid)
);
--
-- The last successfully loaded product workbook, one row per product - so
-- "Edit Product" reopens on the previous upload instead of an empty form.
-- Parsed JSON, not the binary file; same payload-storage pattern as
-- tx_vitec_seo_research. No TCA on purpose.
--
CREATE TABLE tx_vitec_product_workbook (
product_uid int(11) DEFAULT '0' NOT NULL,
filename varchar(255) DEFAULT '' NOT NULL,
payload mediumtext,
be_user int(11) DEFAULT '0' NOT NULL,
tstamp int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (product_uid)
);