News und News-Pages Importer

This commit is contained in:
orasche committed 2026-08-13 17:00:53 +02:00
1 parent 8d3ac08a37
commit f515de54ad
4 files changed
+115554 -3

No files matched your search

@@ -3,9 +3,9 @@
| | |
|---|---|
| **Document identifier** | EVO‑VITEC‑HL‑001 |
| **Version** | 1.7 |
| **Version** | 1.8 |
| **Status** | Released |
| **Date** | 2026‑08‑05 |
| **Date** | 2026‑08‑13 |
| **Applies to** | `evomedien/vitec` on TYPO3 v14.3 (headless) |
| **Owner** | evomedien — VITEC relaunch |
@@ -21,6 +21,7 @@
| 1.5 | 2026‑08‑05 | **Defect fix, output‑changing:** richtext fields were emitted as raw database content by every VITEC UserFunc renderer, leaving `t3://` links unresolved in the JSON. New `RteResolver` service and mandatory convention 9.11; applied at all 19 richtext call sites across 11 renderers. Duplication register 10.2 updated. |
| 1.6 | 2026‑08‑06 | **Interface change (additive):** `tx_vitec_domain_model_download` gained a second category field `type` (display taxonomy; MM rows distinguished by `fieldname`), emitted as the string `type` in the downloadcard, downloadcardcollection and datasheets payloads — analogous to `filetype`. New CLI command `vitec:import-downloads` migrates the old‑site downloads (Collateral directory only; idempotent by slug; files fetched resumably; duplicate `file_url`s merged). |
| 1.7 | 2026‑08‑06 | **Robustness:** the import normalizes legacy filenames on fetch so every imported file matches the version convention (`__NN_A` → `__NN-A`, `___NN` → `__NN`, `__NNA` → `__NN-A`, bare `__NN` → `__NN-A` as initial revision), and the three download renderers gained a `filepath` fallback in `getDownloadFile()` (FAL → convention → filepath) as a safety net for anything that still escapes it. Extends the B‑4 duplication (three copies of the fallback) — consolidation target remains a shared file‑resolver service (10.2). |
| 1.8 | 2026‑08‑13 | **Defect fix and interface change (additive).** Content Blocks never carried the Core *Appearance* tab: `layout`, `frame_class` — including the VITEC frame classes — `space_before_class`, `space_after_class`, `sectionIndex` and `linkToTop` were unreachable for editors on all nine blocks. Added centrally for every `vitec_*` type (7.7); the `appearance` envelope is unchanged, its values were merely always default. Side effect: those six columns now also appear raw inside `data` on top‑level blocks (B‑13), and `appearance.layout` is represented differently on the two envelope paths (B‑14). `intro-paragraph` gained `background_color` (7.7). `vitec_eventlist` gained the layout `regions`, emitting a `regions` array built from the region categories below parent 104; the event payload is specified for the first time (7.14). B‑11 and B‑12 recorded as resolved. |
This document is drafted in the style of, and adopts the terminology conventions of,
ISO/IEC/IEEE 42010 (architecture description), ISO/IEC/IEEE 26514 (information for
@@ -487,6 +488,43 @@ its collection items are resolved explicitly by `UsecaseSerializer::resolveColum
into `{ header…, layout, columns: { left: [], right: [] } }`, with the collection
storage table discovered from TCA (`foreign_table`) rather than hard‑coded.
**Field naming.** Fields carry the `vitec_` vendor prefix in **storage**; the JSON key is
the plain YAML identifier. `ArrayRecursiveToArray` decorates every key with
`TcaFieldDefinition->identifier`, so the column `vitec_background_color` is emitted as
`background_color`. A front end **shall** key on the identifier, never on the column name.
**Field types are whitelisted.** `ArrayRecursiveToArray::processStringField()` switches over
the Content Blocks field types and drops anything that reaches its `default` branch. A new
field type therefore **shall** be verified against the live JSON before it is relied upon;
deriving it from the block definition alone is insufficient.
**Appearance (since v1.8).** Content Blocks builds its own `showitem`
(`TcaGenerator::getContentElementStandardShowItem`) and appends only the *Extended* tab, so
the Core *Appearance* tab was absent from every block.
`Configuration/TCA/Overrides/tt_content.php` now appends
`--div--;core.form.tabs:appearance` together with the **Core
palettes** `frames` and `appearanceLinks` to every `vitec_*` type whose `showitem` lacks
`--palette--;;frames`, positioned ahead of the *Extended* tab. The loop is idempotent, skips
the Extbase plugins (which inherit the tab from `tt_content` `types['header']`) and covers
future blocks automatically.
Redefining those palettes inside a block's `config.yaml` is **prohibited**: TCA palettes are
global per identifier, so a second definition of `frames` collides with the Core one — the
failure mode is a page module that throws `RecordPropertyNotFoundException` at runtime for
*existing* elements, not a build error.
`sectionIndex` and `linkToTop` are **not** part of the `appearance` envelope — `lib.appearance`
carries `layout`, `frameClass`, `spaceBefore` and `spaceAfter` only — and therefore do not
reach the JSON. `sectionIndex` still governs the Core section‑menu element; `linkToTop` is
inert in headless operation.
**Colour fields.** `intro-paragraph` carries `background_color` (`type: Color`): lower‑case
hex, empty string when unset, with the VITEC palette offered as `valuePicker` presets. Hex
is stored lower case deliberately, because the native colour picker emits lower case and an
upper‑case preset would store one colour under two spellings. A block can therefore receive
a background by **two** mechanisms — this field and the `vitec-bg-*` frame classes. The
precedence between them is a front‑end decision and is deliberately not fixed here.
### 7.8 Forms
#### 7.8.1 Form plugin payload
@@ -726,6 +764,65 @@ renderer duplicates no FAL logic.
A Solution list counterpart does not exist yet. When it is added it **should** reuse this
shape under `content.solutions`.
### 7.14 Event list payload (`vitec_eventlist`)
`EventlistJsonRenderer` emits, under `content.eventlist`:
```jsonc
{ "events": [
{ "uid": 1, "title": "…", "slug": "…", "teaser": "…",
"description": "<p>…</p>", // RTE HTML, resolved per 9.11
"eventstart": "2027-07-09", // ISO date, null when unset
"eventend": "2027-07-09",
"venue": "…", "booth": "…", "city": "…", "country": "…",
"attendancemode": "offline", // offline | online | mixed
"eventstatus": "scheduled",
"eventurl": "…", "meetinglink": "…",
"image": { "url": "…", "srcset": [ … ] },
"categories": [ { "uid": 107, "title": "…", "description": "…" } ] } ],
"settings": { "layout": "list", // list | grid | teaserbar | regions
"showpast": false, "daysinadvance": 0, "limit": 0 },
"pastEvents": [ … ], // only when showpast is set
"regions": [ … ] } // only when layout = regions
```
"Upcoming" means `eventend >= today`, or `eventstart >= today` when no end date is set;
ordering is `eventstart` ascending. `pastEvents` inverts both and is present only when the
FlexForm flag `showpast` is set.
#### 7.14.1 Region payload (`layout: regions`)
For the `regions` layout the renderer additionally emits one entry per **region** — the
`sys_category` records directly below the parent category **104** — that has at least one
upcoming event:
```jsonc
{ "uid": 107, "title": "European Events",
"description": "", // plain text; sys_category is not a richtext field
"eventCount": 2,
"image": { "url": "…", "srcset": [ … ] }, // the next event's image, i.e. the region logo
"nextEvent": { "uid": 1, "title": "…", "slug": "…",
"eventstart": "2027-07-09", "eventend": "2027-07-09",
"eventurl": "…" } }
```
Normative behaviour:
- A region **without** an upcoming event is omitted entirely. `showpast` does not
reinstate it — the layout answers "what is coming up where", not "what happened".
- An event filed under a **descendant** of a region counts for that region. The category
branch is resolved in PHP from a single `sys_category` read, per 9.2's preference for one
query over per‑level recursion.
- Ordering is the **backend sorting** of the categories, so the carousel order is editor
controlled. `nextEvent.eventstart` is included so a front end may sort chronologically
instead.
- `daysinadvance` applies. **`limit` does not**: it caps events, and applying it before the
grouping would silently drop whole regions.
- The parent category id is the constant `REGION_PARENT_CATEGORY` in the renderer, not a
FlexForm setting — a hard‑coded literal in the sense of B‑5, accepted here because it
belongs to the content model rather than to a single content element.
An event carrying no category belongs to no region and is invisible to this layout while
remaining present in `events`.
---
## 8 Content‑type catalogue
@@ -742,7 +839,7 @@ shape under `content.solutions`.
| `vitec_downloadcard` | `< lib.…WithHeader` | DownloadcardJsonRenderer | `downloadcard` | detail |
| `vitec_downloadcardcollection` | `< lib.…WithHeader` | DownloadcardcollectionJsonRenderer | `downloadcardcollection` | list |
| `vitec_datasheets` | `< lib.…WithHeader` | DatasheetsJsonRenderer | `datasheets` | list |
| `vitec_eventlist` | `=< lib.…WithHeader` ⚠ | EventlistJsonRenderer | `eventlist` | list |
| `vitec_eventlist` | `=< lib.…WithHeader` ⚠ | EventlistJsonRenderer | `eventlist` | list (7.14) |
| `vitec_locationlist` | `< lib.…WithHeader` | LocationsJsonRenderer | `locations` | list (global) |
| `vitec_customerlogos` | `< lib.…WithHeader` | CustomerlogosJsonRenderer | `customerlogos` | list |
| `vitec_modelcard` | `< lib.…WithHeader` | ModelcardJsonRenderer | `card` | detail (4 model types) |
@@ -1040,11 +1137,33 @@ remediation.
as intended. Related: `ModelcardJsonRenderer` serves `market` and `solution` from one
shared branch and therefore emits no `detailUrl` either — the card payload (7.9) cannot
link to a market detail page until this is resolved.
**Resolved 2026‑08‑10:** `detail_page` added to Solution with the identical TCA shape and
emitted by `SolutionShowJsonRenderer`; the shared `market | solution` branch of
`ModelcardJsonRenderer` now serialises `detailUrl`, so market cards link as well.
- **B‑12 — `detailUrl()` duplicated** in `MarketListJsonRenderer` and
`MarketShowJsonRenderer`, and a third near‑identical `resolveLink()` lives in
`LocationsJsonRenderer` (7.10). Three copies of "resolve a link server side" is the
smallest concrete case of B‑4; it is the natural seed for the `LinkResolver` service
that 10.2 calls for.
**Resolved 2026‑08‑10:** `Service\LinkResolver::pageUrl()` is now the single
implementation, with five callers. The contract is **`null` = no link**; the two Usecase
renderers keep a thin wrapper appending `?? ''` because they build paths by concatenation.
`LocationsJsonRenderer` and `NewsJsonRenderer` stay outside it deliberately — the first
resolves a whole `parameter` construct, the second builds slug paths plus a canonical, and
neither is a page‑uid‑to‑URL mapping.
- **B‑13 — Appearance columns duplicated inside `data`.** Since the *Appearance* tab was
added (7.7), `Record::toArray()` resolves the six palette fields as part of the record, so
**top‑level** Content Blocks emit `layout`, `frame_class`, `space_before_class`,
`space_after_class`, `sectionIndex` and `linkToTop` raw inside `data` in addition to the
processed `appearance` object. Container children are unaffected, being serialised by
`ContainerChildrenProcessor` rather than `RecordToArray`. Harmless but redundant, and the
raw and processed representations of `layout` differ (B‑14). Removable through a
`ModifyArrayRecursiveToArrayEvent` listener.
- **B‑14 — `appearance.layout` is not represented uniformly.** On the TypoScript path a
`CASE` in `lib.appearance` maps the field to `default` / `layout-1` / `layout-2` /
`layout-3`; container children serialised by `ContainerChildrenProcessor` carry the raw
value (`"0"`). A front end consuming both paths must accept either form. Predates v1.8;
recorded here because the Appearance tab makes the field editable in the first place.
---