- New record type tx_vitec_domain_model_searchcard ("best bets"):
keyword list, priority, optional referenced record (page, product,
story, solution, market, news) and overridable title/teaser/image/link;
hidden/start/end time allow timed campaigns
- SearchCardService delivers content.search.cards on page 1: max. 3,
priority-ordered, deduplicated by URL, independent of filter, facets
and result count. Keywords match as whole words/phrases, case- and
punctuation-insensitive, including one level of the Solr managed
synonyms in both directions (cached for an hour, fail-soft). Record
cards read the record's indexed Solr document, so a card always
matches the record's own search result
- Index fallback for markets and solutions: when the record carries no
image or text, the document takes the intro image (then the hero
background) and the hero subline, intro headline and intro text from
the content blocks of its detail page - selected by CType, so it works
for layout 21 and layout 5 alike; improves results and cards
- Fix: a search request without q returned an empty body instead of the
documented empty shape (stdClass resolved inside the renderer namespace)
- migrations/check_solution_fields.php: shows live/workspace versions of
solution records
- Spec v1.22 (clause 7.16: cards)
the customer workflow in mind: the customer fills one XLSX per sub-market,
an importer builds the page).
- Frontend layout 21 'Sub-Market Page' in the existing
BackendLayoutDataProvider: six zones, one per Figma section, emitted as
colPos110..colPos160 - the JSON groups plus appearance.layout are the
front-end contract (spec clause 7.17). A first attempt via page-TSconfig
BackendLayouts was the wrong mechanism next to the provider and was
removed again
- New Content Blocks vitec_markethero, vitec_marketintro,
vitec_marketinsights (field bags, serialized unprefixed under data);
the workflow section reuses intro-paragraph + vitec_card flip cards
- Stories gained quote/quote_person/quote_role (Testimonial tab),
maintained once per story, emitted on every story card; usecaselist
gained the layout value 'testimonials'
- New plugin vitec_productfeature: one referenced product as a full
product card, serialisation shared with the product list (cObj made
protected for the subclass)
- vitec_productlist gained hand-picked product selection: exactly the
chosen products in the editor's order, category filter ignored,
visibility filters kept - closes the long-standing single-select gap
- New CLI vitec:generate-submarket-workbooks: one protected customer
XLSX per sub-market (9 main markets, 25 sub-markets from the Market
category tree) - dropdowns filled live from the database, named ranges
as the importer contract, hidden Meta sheet pinning submarket/group/
record uid, soft character-limit warnings, asset URL fields
Verified end to end on Broadcast & Media: layout-21 payload with colPos110
carrying the hero element and its subline. Spec raised to v1.20.
feedback widget served from /api/fe-comment/widget.js, note pad in
localStorage, submissions mailed via /api/fe-comment/submit with
recipients from the extension configuration; classic sites get the
script injected via AssetCollector when the jsonOutput setting is off.
An enabled master switch serves the widget EMPTY when off (no 404, no
console errors) and rejects submissions - the go-live kill switch, no
front-end build change needed
- URL swap finished: /_json prefix middleware, SPA fallback live with a
dedicated root rule (REQUEST_FILENAME of / is a directory) and a
query-string exception for the TYPO3 v14 install tool entry
(?__typo3_install on the site root - the backend Settings/Environment
modules depend on it); /api/ as a whole stays with TYPO3
- MailMessage::send() no longer exists in v14: fe_comment and the form
EmailDelivery (latently broken since the core upgrade) now send through
the Mailer service. Mail transport moved to SMTP against the local exim
so delivery errors surface instead of bouncing into the blackhole -
exim verifies the envelope sender, which therefore must be a routable
existing address (transport config lives in the untracked settings.php)
- Related-product card texts editable on the product record (table rebuilt
with uid/pid, TCA + inline field, one-time migration script); shared
RteCompare for the module badge and the CLI comparison - batch dry-run
now reports 0 writes instead of flagging every richtext field
- Workbook clarification cases executed: VisionIO-SD14, VisionSC-SD14 and
both Diamond OG records imported (40 fields, live-verified); ArtioSign
and ArtioView created hidden (uid 109/110) via
create_artio_records.php - the product table has no sorting column;
WallControl_10 mapping REVERTED and parked: the dry run revealed
aetria-wallcontrol already carries its own agency workbook, which
WallControl_10 would have overwritten. Manifest now 75 product /
24 family / 1 open
Apache Solr 10 runs on a dedicated VPS behind a Caddy HTTPS proxy
(vitecsolr.evomedien.de) because the managed webserver only allows
outgoing standard ports. Credentials stay out of git: the site config
carries %env()% placeholders resolved via putenv() in the git-ignored
config/system/additional.php.
- composer: apache-solr-for-typo3/solr 14.0.0-RC1 (the only line
compatible with TYPO3 14; final 14.0.0 will arrive via composer update)
- config.yaml: read connection https/443, core_en per language,
env placeholder credentials; .gitignore covers additional.php
- setup.typoscript: config.index_enable = 1 (page indexing silently
refuses without it), solr_pi_results JSON renderer registration,
results highlighting, and content field extraction from tt_content
rows - the headless JSON output has no TYPO3SEARCH markers, so the
default page content extraction indexed an empty content field
- SearchJsonRenderer (renderer #27): JSON output for the search plugin
on /search. GET q/page in; { query, page, resultsPerPage, numFound,
totalPages, results[], suggestions } out. Disables the page cache per
request: config.no_cache is gone in TYPO3 v14, and q/page are
excluded from cHash, so cached variants would collide
- ext_localconf.php: q and page added to cacheHash excludedParameters
- SolrIndexCommand (vitec:solr-index): works the index queue from the
CLI with connection diagnostics and a --debug single-step mode -
EXT:solr 14 ships no console commands and the backend button indexes
one item per click
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
- vitec_usecaselist: layout + record selection like marketlist
- new plugin vitec_solutionlist (spec 7.13.3, key "solutions")
- tx_vitec_domain_model_usecase: detail_page -> resolved detailUrl
(also gives story cards in vitec_modelcard a link for the first time)
- "Show Toolbar" checkbox on product/market/solution/usecase lists
- spec bumped to v1.9
BREAKING: vitec_productlist and vitec_usecaselist now emit an object
instead of a bare array. Consumers must read products.products and
usecases.usecases. Also found: productlist had a configurable layout
that was never serialised; it is emitted now, but keeps its own 0-3
vocabulary instead of grid/list/carousel.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
Resolves a cascade of TYPO3 v14 breaking changes that left every VITEC
plugin's JSON output silently empty:
1. `list_type` column dropped — all renderer page-discovery queries now
filter by `CType = 'vitec_X'`.
2. `#[AsAllowedCallable]` attribute added to every public render() —
without it v14 throws AllowedCallableException, which headless
silently filters via its "Oops, an error occurred!" guard.
3. `$GLOBALS['TSFE']->id` is null inside JSON cObj context — page id
now read from the `frontend.page.information` request attribute
(TSFE fallback kept for legacy entry points).
4. page.tsconfig wizard items migrated to `CType = vitec_X` directly
(legacy `CType=list, list_type=...` no longer exists in v14).
5. ContainerChildrenProcessor + ContentElementResolver dispatch the
PLUGIN_RENDERERS map by CType (primary) with list_type fallback.
Beyond the bug fix this commit also contains:
- Datasheets renderer rewritten to "products with newest datasheet"
semantics (filtered via Download.hideondatasheets).
- New vitec/card content block — multi-purpose card with backend
preview and layout/background/aspect/alignment/border/shadow options.
- New vitec_container CType (b13 single-column container, FlexForm
cssClass propagated into the JSON envelope).
- ContentElementResolver service for contentelement/contentelementcta
link resolution; ContainerChildrenProcessor for nested plugin
resolution inside b13 containers.
- Vitecset setup.typoscript: ContentElement import moved to top so
lib.contentElement is defined before VITEC's tt_content blocks.
- Cleanup: 98 .bak.<timestamp> debugging backups removed; *.bak.* and
/public/_assets_install/ added to .gitignore.
Resolves a cascade of TYPO3 v14 breaking changes that left every VITEC
plugin's JSON output silently empty:
1. `list_type` column dropped — all renderer page-discovery queries now
filter by `CType = 'vitec_X'`.
2. `#[AsAllowedCallable]` attribute added to every public render() —
without it v14 throws AllowedCallableException, which headless
silently filters via its "Oops, an error occurred!" guard.
3. `$GLOBALS['TSFE']->id` is null inside JSON cObj context — page id
now read from the `frontend.page.information` request attribute
(TSFE fallback kept for legacy entry points).
4. page.tsconfig wizard items migrated to `CType = vitec_X` directly
(legacy `CType=list, list_type=...` no longer exists in v14).
5. ContainerChildrenProcessor + ContentElementResolver dispatch the
PLUGIN_RENDERERS map by CType (primary) with list_type fallback.
Beyond the bug fix this commit also contains:
- Datasheets renderer rewritten to "products with newest datasheet"
semantics (filtered via Download.hideondatasheets).
- New vitec/card content block — multi-purpose card with backend
preview and layout/background/aspect/alignment/border/shadow options.
- New vitec_container CType (b13 single-column container, FlexForm
cssClass propagated into the JSON envelope).
- ContentElementResolver service for contentelement/contentelementcta
link resolution; ContainerChildrenProcessor for nested plugin
resolution inside b13 containers.
- Vitecset setup.typoscript: ContentElement import moved to top so
lib.contentElement is defined before VITEC's tt_content blocks.
- Cleanup: 98 .bak.<timestamp> debugging backups removed; *.bak.* and
/public/_assets_install/ added to .gitignore.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New Classes/Service/ContentElementResolver.php: parses TYPO3 typolink
(t3://record?identifier=tt_content&uid=N, t3://page?uid=P#N, plain numeric)
to a normalised tt_content envelope ({id,type,colPos,sorting,appearance,
data}), recursively resolving any nested VITEC list-plugin children.
- ProductListJsonRenderer / ProductShowJsonRenderer: contentelement and
contentelementcta now emit the resolved object instead of the raw
typolink string (breaking change at those two keys).
- Product model: new field videofile (FAL, single video upload in tab
Images and Videos, mp4/webm/ogv/mov/m4v); new bool field showdatapath
(toggle at end of General tab, controls the "Datapath is now Vitec"
graphic in the frontend). ext_tables.sql, TCA, model property +
getter/setter, and both renderers updated accordingly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>