diff --git a/typo3-v11-to-v14-ddev-upgrade/SKILL.md b/typo3-v11-to-v14-ddev-upgrade/SKILL.md index 23bf1ad..d1cdab0 100644 --- a/typo3-v11-to-v14-ddev-upgrade/SKILL.md +++ b/typo3-v11-to-v14-ddev-upgrade/SKILL.md @@ -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, or when a t3bootstrap-based v11 site needs its composer/config/schema/upgrade-wizards/site-sets brought to v14. 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, 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, 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.0" + version: "1.1" --- # TYPO3 v11 → v14 upgrade (local, DDEV) @@ -101,6 +101,51 @@ local DDEV is fine. `ddev exec vendor/bin/typo3 language:update`. Composer mode ships **no** language packs → labels fall back to English (e.g. news "more-link"). Run this whenever the site language isn't English. +## Step 8c — Non-admin editor permissions (⚠ the migration does NOT fix these) +Very confusing symptom: a **non-admin editor** (e.g. a "Redakteur" group) opens the Page module, **sees +the content but there are no edit icons**, and/or the **Media tab is missing** from the content form — +while the Access (Berechtigungen) module shows the group *has* "edit content" and `tables_modify` includes +`tt_content`. Cause: the v11→v14 upgrade wizards do **not** convert the backend group access-lists. Fix +three separate `be_groups` fields, per editor group (find it: `SELECT uid,title FROM be_groups WHERE +deleted=0`). Editors must **log out/in** afterwards. + +1. **`explicit_allowdeny` format — THE big one (blocks ALL content editing).** v≤11 stored allowed values + as `tt_content:CType:text:ALLOW`; **v12+ dropped the suffix** and `BackendUserAuthentication:: + checkAuthMode()` does an exact `GeneralUtility::inList()` against `tt_content:CType:text` (no suffix). + The migrated `:ALLOW` never matches → every CType (even plain Text/Header) is denied → no edit icons on + anything. Strip the suffix (all groups): + `UPDATE be_groups SET explicit_allowdeny = REPLACE(explicit_allowdeny, ':ALLOW', '') WHERE deleted=0` + (`:DENY` entries may stay — `…:value:DENY` never equals `…:value`, so the value correctly stays + non-allowed.) Verify: `FIND_IN_SET('tt_content:CType:text', explicit_allowdeny) > 0`. +2. **Missing v14 CType names in the allow-list.** The container migration renamed CTypes `wst3bootstrap_*` + → `t3bs_*`; the allow-list only has the old names. Append the new names actually used — compare + `SELECT DISTINCT CType FROM tt_content` vs the list and add `tt_content:CType:` (NO `:ALLOW` + suffix) for each missing one; typically `t3bs_fluidrow/_column/_tabs/_tab_item/_accordion/ + _accordion_item/_megamenu`, `ws_slider`, `heroitem`, `news_*`, `address_*`. +3. **`non_exclude_fields` missing v14 fields → hidden tabs (e.g. Media).** TCA `exclude` fields are hidden + from non-admins unless granted here (format `table:field`, unchanged in v12). The v11 list lacks fields + ADDED in v14, so any tab whose fields are ALL exclude+denied won't render — e.g. the hero **Media** tab + contains only `tx_heroitem_bg`/`_bg_tablet`/`_bg_smartphone` (all denied → no tab). Grant the missing + `tt_content` exclude fields (append `tt_content:` for each). Common culprits: `imagecols_grid, + effects, aos_*, bg_container, tx_wsslider_{renderer,layout,source}, tx_heroitem_*, tx_teaser2_layout`. + NOTE `image`/`assets`/`media` are NOT exclude fields (always shown) — the missing tab is the *settings* + fields, not the FAL field. Other record types editors touch (news, address) can be stale the same way. + +**Diagnose precisely — read-only CLI bootstrap** (also the way to *confirm* a fix without a BE login): +```php +SystemEnvironmentBuilder::run(0, SystemEnvironmentBuilder::REQUESTTYPE_CLI | SystemEnvironmentBuilder::REQUESTTYPE_BE); +Bootstrap::init($classLoader); +$be = GeneralUtility::makeInstance(BackendUserAuthentication::class); +$be->user = BackendUtility::getRecord('be_users', ); $be->fetchGroupData(); $GLOBALS['BE_USER'] = $be; +$be->recordEditAccessInternals('tt_content', $row, false, false, true); // false → $be->errorMsg names the failing gate +$be->check('non_exclude_fields', 'tt_content:'); // tab/field visibility +$be->doesUserHaveAccess($pageRow, 16); // page "edit content" perm +``` +`recordEditAccessInternals` failing with `authMode "explicitAllow" failed for field "CType"` == facet 1/2. +(Writing `be_groups` *from* such a script may be blocked by agent tooling — apply fixes as plain SQL +`UPDATE`/`REPLACE`/`CONCAT`.) Red herring: an empty `db_mountpoints` on the user is fine if the group (or a +subgroup) supplies a mount — check the user's *effective* `getWebmounts()` before chasing it. + ## Step 9 — Wire TypoScript via site sets v14 t3bootstrap delivers TypoScript (incl. the `PAGE` object) through **site sets**, not `sys_template`. The site config must declare them under `dependencies:` in `config/sites//config.yaml`, or the