Sechs Erkenntnisse aus einem Ticketdurchlauf einarbeiten
Upgrade-Skill 1.3 - neuer Step 9b: die uebrig gebliebenen sys_template- Datensaetze loeschen. "Via site sets, not sys_template" liest sich wie "die Tabelle ist erledigt", aber v14 wertet sie weiter aus (TCA in cms-frontend, PageInformationFactory ruft getSysTemplateRowsByRootline). Ein Alt-Template mit clear=3 OBERHALB des Site-Roots loescht Constants und Setup, also auch das Set-TypoScript - und zwar nur fuer Code, der das FE-TypoScript im Backend mit eigener Rootline neu aufbaut, weil der Core die Rootline am Site abschneidet. Symptome sehen unverwandt aus (fehlende FormEngine-Platzhalter, leere Template-Layout-Listen, nicht erscheinende FlexForm-Sheets), Kennzeichen ist: Frontend richtig, Backend falsch. Mit den drei Pruefungen, die das Loeschen vorher absichern, und Soft-Delete statt DELETE. Design-Parity 1.9 - drei Punkte: - Vergleichsschleife: um zu belegen, dass ein Eingriff das Frontend NICHT veraendert, muss vor dem Diff das Render-Rauschen weggefiltert werden (picture-/img-Hashes, CSS-mtime), sonst weicht jede Seite ab und der Beweis faellt aus. - Neuer Abschnitt zum Backend-Formular mit Playwright: es steckt in einem iframe (und der naheliegende Frame-Filter erwischt den Hauptframe mit), innerText ist in inaktiven Tabs LEER, auf den eigenen field-item eingrenzen, Tab-Aktivierung ist unzuverlaessig, den SAVE testen - und die UI-Reichweite einer Aenderung an einer FormEngine-Renderbedingung vorher/nachher zaehlen (aus 9 Schaltern wurden unbemerkt 83). - Settings: Booleans in settings.yaml gehoeren in Anfuehrungszeichen. YAML true wird zum Constant "1", YAML false zu einem LEEREN Constant; das Frontend ueberlebt es, der Backend-Platzhalter nicht. Deploy-Skill 1.3 - die dort empfohlene Form MYSQL_PWD="$(cat …)" wird fuer Schreibzugriffe regelmaessig blockiert. Durchgegangen ist ein Skript, das das Passwort selbst aus DBPASSFILE liest, sodass nur ein Pfad in der Kommandozeile steht. Dazu: solche Skripte gezielt und idempotent auf dem aktuell gespeicherten Stand arbeiten lassen statt ein vorbereitetes Blob zurueckzuschreiben, sonst ueberfaehrt man den parallelen Save eines Redakteurs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ name: typo3-konsoleh-staging-deploy
|
||||
description: "Deployt ein lokal mit DDEV gebautes TYPO3-Projekt (v13/v14, Composer) als Staging-Seite auf einen Hetzner-Managed-Webhosting-Server (konsoleH). Der Composer-Build läuft AUF dem Server (kein vorgefertigtes vendor/ wird hochgeladen). Verwenden, wenn eine TYPO3-Staging- oder Vorschau-Umgebung auf Hetzner Managed Hosting (konsoleH), einem *.your-server.de-Host oder dedi*-Server eingerichtet werden soll, oder wenn eine lokale DDEV-TYPO3-Seite per SSH auf ein Managed-/Shared-Hosting übertragen werden soll. Umfasst: SSH-Inventar, per-User-composer.phar, Deploy-Keys für private Git-Repos (gitea) + Registry-Auth, Datenbank + Dokumentstamm über konsoleH, rsync von Quellcode + fileadmin, DB-Import, Staging-additional.php, .htaccess, Sprachpakete, HTTP-Basic-Auth und Let's Encrypt. NICHT für Root-VPS-/Docker-/DDEV-auf-dem-Server-Deployments."
|
||||
metadata:
|
||||
author: Wappler
|
||||
version: "1.2"
|
||||
version: "1.3"
|
||||
---
|
||||
|
||||
# TYPO3 → Hetzner konsoleH staging deployment
|
||||
@@ -218,6 +218,24 @@ The environment blocks any command containing a **literal live credential**. So:
|
||||
and the TYPO3 password/registry token **interactively** in their own SSH session.
|
||||
- Your admin commands read the DB password from the file: `MYSQL_PWD="$(cat …/.env.db)" mysql …` —
|
||||
the literal secret never appears in the command text.
|
||||
- **⚠ That form is still frequently BLOCKED for writes.** Substituting a secret file into the command
|
||||
line reads as a credential-bearing command, so every remote `UPDATE`/`DELETE` gets refused. Don't
|
||||
fight it and don't fall back to pasting the password: **let the script read the file itself**, so the
|
||||
command carries only a path.
|
||||
```
|
||||
# passes: only a file PATH on the command line, no substitution
|
||||
$SSH 'cd ~/public_html/<PROJECT> && DBHOST=<DB_HOST> DBNAME=<DB_NAME> DBUSER=<DB_USER> \
|
||||
DBPASSFILE=config/system/.env.db php var/<task>.php <args>'
|
||||
```
|
||||
and in the script: `$pw = rtrim(file_get_contents(getenv('DBPASSFILE')), "\r\n");` → `new mysqli(...)`.
|
||||
This got both reads and writes through where `MYSQL_PWD="$(cat …)"` was refused. Delete the script
|
||||
from the server afterwards — a one-off PHP file in the project is exactly what the cutover skill makes
|
||||
you hunt for later.
|
||||
- **Make such a script targeted and idempotent, never a blob write-back.** Have it change only the named
|
||||
keys/fields **in whatever is currently stored** — read, modify, write — instead of pushing a
|
||||
pre-built value you generated earlier. On a customer system editors work while you do: a blob
|
||||
write-back silently discards their concurrent save, and re-running it is unsafe. Targeted edits can
|
||||
be re-run at will and print a before/after line per key, which doubles as the record of what changed.
|
||||
- Never write a password into a command, a config file you author, or the transcript. `additional.php`
|
||||
reads the password from `.env.db`; it never embeds it.
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: typo3-t3bootstrap-live-design-parity
|
||||
description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule), the settings-vs-SCSS decision, the t3b_core spacing system (spacing.yaml / tx_t3b_spacing) and why spacing must never be fixed in SCSS, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel incl. why Bootstrap autoplay cannot be switched off via the interval), diagnosing regressions caused by an editor's SAVE (CKEditor dropping undeclared classes, FlexForm selects with no empty item flipping to "yes"), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)."
|
||||
description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule, and how to prove a change did NOT alter the frontend), driving the BACKEND record form/FormEngine with Playwright (it lives in an iframe; innerText is empty in inactive tabs), the settings-vs-SCSS decision incl. why settings.yaml booleans must be quoted strings, the t3b_core spacing system (spacing.yaml / tx_t3b_spacing) and why spacing must never be fixed in SCSS, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel incl. why Bootstrap autoplay cannot be switched off via the interval), diagnosing regressions caused by an editor's SAVE (CKEditor dropping undeclared classes, FlexForm selects with no empty item flipping to "yes"), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)."
|
||||
metadata:
|
||||
author: Wappler
|
||||
version: "1.8"
|
||||
version: "1.9"
|
||||
---
|
||||
|
||||
# TYPO3 v14 t3bootstrap — live-design parity
|
||||
@@ -77,10 +77,50 @@ placeholders below from the site you're matching; keep a per-project log of what
|
||||
it decides whether anything you measure afterwards means something. `curl` is NOT a substitute
|
||||
behind HTTP basic auth (staging) — it returns 401 while the browser holds the credentials.
|
||||
Test behaviour only after that fetch and the DOM agree.
|
||||
- **To prove a change did NOT alter the frontend, diff the HTML — but normalise the per-render noise
|
||||
first.** TYPO3 emits values that differ on every render, so a raw `diff` reports every page as
|
||||
changed and the proof evaporates: `id="picture-<hash>"` / `id="img-<hash>"` on responsive images
|
||||
(regenerated per render), and the `?<mtime>` on `main.css`/`fonts.css` after any `cache:flush`
|
||||
recompile. Filter those, then diff:
|
||||
```
|
||||
norm() { sed 's|/typo3temp/assets/css/[^"]*|CSS|g; s|picture-[0-9a-f]*|P|g; s|img-[0-9a-f]*|I|g'; }
|
||||
diff <(norm < before.html) <(norm < after.html) && echo "identisch"
|
||||
```
|
||||
Capture the "before" over **several** pages (a content page, the home page, one with news teasers)
|
||||
before touching anything — after the change it is too late. This is the evidence that turns "I
|
||||
think nothing broke" into "4 pages byte-identical".
|
||||
2. With `browser_evaluate`, capture the real element's **computed style AND its explicit CSS rule**
|
||||
(getComputedStyle + walk `document.styleSheets` for the selector). Don't assume inheritance.
|
||||
3. Diff vs DDEV → decide **setting vs SCSS** (below) → apply → flush → re-screenshot → verify.
|
||||
|
||||
## Driving the BACKEND with Playwright (FormEngine)
|
||||
Sooner or later the question is "what does the editor actually see in this field?" — the record form is
|
||||
a different beast from the frontend, and four things silently produce wrong measurements. Each of these
|
||||
cost a wasted measurement round:
|
||||
- **⚠ The record form lives in an `iframe`.** `document.querySelectorAll(...)` on the main document
|
||||
returns **0 fields** and looks like an empty form. Use `page.frames()`. And beware the obvious
|
||||
selector: `page.frames().find(f => f.url().includes('record/edit'))` matches the **main** frame too,
|
||||
because the outer URL contains that path — pick `f => f !== page.mainFrame()` instead.
|
||||
- **⚠ `innerText` returns EMPTY for anything in an inactive FormEngine tab.** FlexForm sheets are tabs,
|
||||
so every field outside the active one reads as blank — which looks exactly like "no label / no hint
|
||||
rendered". Use **`textContent`**, which ignores visibility. (`offsetParent === null` likewise only
|
||||
means "its tab isn't open", not "hidden".)
|
||||
- **Scope to the field's own `.t3js-formengine-field-item`.** Walking up to a parent to find some text
|
||||
pulls in the neighbouring fields' hints and produces confident nonsense (a hint from the field *above*
|
||||
attributed to this one).
|
||||
- **Activating a tab is unreliable.** `getByRole('tab', {name})` timed out and a JS `.click()` on
|
||||
`[role="tab"]` did nothing on v14. Don't fight it: read via `textContent` regardless of the active
|
||||
tab. Buttons work normally — `button[name="_savedok"]` is Save.
|
||||
- **Test the SAVE, not just the render**, whenever the concern is "does the stored configuration
|
||||
survive?" Press Save in the real form, then check the DB and the frontend. That is the only test that
|
||||
reproduces what an editor does, and it is where FlexForm bugs actually surface.
|
||||
- **⚠ Count the affected widgets BEFORE and AFTER changing a FormEngine element's render condition.**
|
||||
These blocks often render more than they appear to — a placeholder block can also carry the nullable
|
||||
"Set element specific value" toggle, so a change to *when* it renders silently adds or removes that
|
||||
control. A one-line fix of mine turned 9 toggles into **83** (and the naive variant would have removed
|
||||
all 9); only counting `.t3js-form-field-eval-null-placeholder-checkbox` in the real form before and
|
||||
after revealed it. Then choose the variant that keeps the previous footprint.
|
||||
|
||||
## When the report is a rendering artefact, not a defect
|
||||
Some "it looks broken" reports are sub-pixel rasterisation: a hairline that washes out, a circle whose
|
||||
cap renders as a straight edge, an outline that vanishes. They are **display-dependent**, which is why
|
||||
@@ -106,6 +146,15 @@ one person sees them and another does not, and why they come and go with the zoo
|
||||
a bug fix. Do not ship a change that your own numbers say is not an improvement.
|
||||
|
||||
## Settings vs SCSS decision
|
||||
- **⚠ Write booleans in `settings.yaml` as QUOTED STRINGS, not YAML booleans.** Site settings arrive in
|
||||
TypoScript as constants, and the conversion is lossy: YAML `true` becomes the constant **`"1"`** and
|
||||
YAML `false` becomes an **EMPTY** constant. The frontend usually survives that (a falsy check, or an
|
||||
extension mapping `'true'`/`'false'` to real booleans), so it looks fine and the bug hides in the
|
||||
backend: an option field whose items are the strings `true`/`false` can no longer match the constant,
|
||||
so its "Default: …" hint shows `Default: "1"` — or, for the empty case, matches the FIRST item and
|
||||
claims `Default: "Default"`. With `'true'` / `'false'` the mapping works and the hint reads
|
||||
`(Default: "Yes"/"No")`, with identical frontend output. Applies to any `plugin.tx_*` value you set
|
||||
through `settings.yaml`, not just declared theme settings.
|
||||
- **Setting** (`config/sites/<SITE_ID>/settings.yaml`) for anything mapped in the theme's
|
||||
`Configuration/TypoScript/Plugin/Setup/tx_wsscss.typoscript`: `design.color.{primary,secondary,
|
||||
body-color,headings-color,header-bg,page-bg,footer-bg,footer-color,footer-headline-color,…}`,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: typo3-v11-to-v14-ddev-upgrade
|
||||
description: "Bring an existing TYPO3 v11 site up and booting on TYPO3 v14 LTS (v14.3) locally under DDEV, starting from a v11 SQL dump + the old sitepackage. Use when upgrading/migrating a TYPO3 v11 (or v12/13) project to v14 for local dev, when a v11 database dump must be made to boot on v14, when a t3bootstrap-based v11 site needs its composer/config/schema/upgrade-wizards/site-sets brought to v14, or when after such an upgrade a non-admin editor can't edit content (no edit icons / missing Media tab). Covers: composer.json rework to ^14 + private git repos & composer registry auth, config/system/settings.php, the v14 .htaccess, database:updateschema, backend admin, upgrade wizards (incl. confirmable + one-way ones), language packs, wiring t3bootstrap TypoScript via site sets, fixing non-admin editor permissions (be_groups explicit_allowdeny :ALLOW-format conversion, v14 CType allow-list, non_exclude_fields), and the recurring v11->v14 traps. NOT for fresh installs and NOT for server deployment (see the konsoleH staging-deploy skill for that)."
|
||||
description: "Bring an existing TYPO3 v11 site up and booting on TYPO3 v14 LTS (v14.3) locally under DDEV, starting from a v11 SQL dump + the old sitepackage. Use when upgrading/migrating a TYPO3 v11 (or v12/13) project to v14 for local dev, when a v11 database dump must be made to boot on v14, when a t3bootstrap-based v11 site needs its composer/config/schema/upgrade-wizards/site-sets brought to v14, or when after such an upgrade a non-admin editor can't edit content (no edit icons / missing Media tab). Covers: composer.json rework to ^14 + private git repos & composer registry auth, config/system/settings.php, the v14 .htaccess, database:updateschema, backend admin, upgrade wizards (incl. confirmable + one-way ones), language packs, wiring t3bootstrap TypoScript via site sets, deleting the leftover sys_template records that keep breaking BACKEND features after that switch (a clear=3 template above the site root wipes the site-set TypoScript for anything that rebuilds it), fixing non-admin editor permissions (be_groups explicit_allowdeny :ALLOW-format conversion, v14 CType allow-list, non_exclude_fields), and the recurring v11->v14 traps. NOT for fresh installs and NOT for server deployment (see the konsoleH staging-deploy skill for that)."
|
||||
metadata:
|
||||
author: Wappler
|
||||
version: "1.2"
|
||||
version: "1.3"
|
||||
---
|
||||
|
||||
# TYPO3 v11 → v14 upgrade (local, DDEV)
|
||||
@@ -153,6 +153,37 @@ FE dies with **"No page configured for type=0"**. Add the set identifiers (the `
|
||||
`Configuration/Sets/*/config.yaml` — independent of package name/extkey), e.g. the theme set +
|
||||
container-bs5-templates + news/form/address/blog/slider as used. See the design skill for details.
|
||||
|
||||
### ⚠ Step 9b — Delete the leftover `sys_template` records (they are NOT harmless)
|
||||
"Via site sets, not `sys_template`" says where the theme's TypoScript comes from — it does **not** mean
|
||||
the table is out of the picture. **v14 still evaluates it**: `sys_template` has a TCA
|
||||
(`EXT:frontend/Configuration/TCA/sys_template.php`) and the frontend calls
|
||||
`SysTemplateRepository::getSysTemplateRowsByRootline()` from `PageInformationFactory`. The v11 dump
|
||||
brings the old records along and nothing in the upgrade removes them.
|
||||
```
|
||||
SELECT uid,pid,title,root,clear,hidden,deleted,basedOn,include_static_file FROM sys_template ORDER BY pid,uid;
|
||||
```
|
||||
**The dangerous one has `clear=3` and sits ABOVE the site root.** `clear` is a bitmask (1=constants,
|
||||
2=setup), so `3` clears everything included before it — **including the site-set TypoScript**. The
|
||||
frontend never notices, because core cuts the rootline at the site (`$rootLine = $rootLineUntilSite;`
|
||||
immediately before the repository call). But anything that rebuilds FE TypoScript in the **BACKEND**
|
||||
with its own rootline does: such code typically walks to pid 0 via `RootlineUtility`, picks the old
|
||||
template up, and ends with an empty setup. The symptoms are silent and look unrelated — FormEngine
|
||||
placeholders showing nothing or nonsense, empty "template layout" lists, FlexForm sheets that appear
|
||||
only when a renderer field is set explicitly, Extbase BE modules reading plugin settings.
|
||||
**Tell-tale: the FE is right while the BE is wrong.** Confirm by checking the built array for the branch
|
||||
you expect (e.g. `plugin.tx_<ext>.`): missing there while the FE renders fine ⇒ this is it. Measured on
|
||||
one project: a single such record suppressed 139 of 148 backend placeholders.
|
||||
**Prove it is safe BEFORE deleting** — three cheap checks:
|
||||
1. Is its page **above** the site root (`pages.is_siteroot=1`)? Then the FE never included it.
|
||||
2. Is `basedOn` empty on **every** template? Otherwise you break an include chain.
|
||||
3. Do its `include_static_file` / constants name extensions that no longer exist
|
||||
(`EXT:<old_sitepackage>/…`)? Then it is pure v11 residue.
|
||||
**Prefer `deleted=1` over `DELETE`** (reversible, and what the backend itself would do), snapshot first,
|
||||
and verify afterwards by diffing a few rendered pages — normalise the per-render noise first (see the
|
||||
design skill's compare loop), else every page looks changed.
|
||||
⚠ Leave records **inside** the site alone until checked: a `root=1` template on the site root IS in the
|
||||
FE rootline, even if its constants point at a dead extension.
|
||||
|
||||
## Step 10 — Flush + verify
|
||||
`ddev exec vendor/bin/typo3 cache:flush`. Verify over HTTP with the **correct host**: `/typo3/` → 200,
|
||||
FE with `curl -H "Host: <SITE_BASE_HOST>" …` (or the real DDEV URL) → 200. **"No site configuration
|
||||
|
||||
Reference in New Issue
Block a user