TYPO3 Extension Upgrade Skill
Framework for upgrading TYPO3 extensions to newer LTS versions.
Extension code only, not project/core upgrades.
Upgrade Toolkit
| Tool |
Purpose |
Files |
| Extension Scanner |
Diagnose deprecated APIs |
TYPO3 Backend |
| Rector |
Automated PHP migrations |
.php |
| Fractor |
Non-PHP migrations |
FlexForms, TypoScript, YAML, Fluid |
| PHPStan |
Static analysis |
.php |
Core Workflow
- Complete planning phase (consult
references/pre-upgrade.md)
- Create feature branch (verify git is clean)
- Update
composer.json constraints for the target version. v14's LTS minor is 3: write ^14.3, never ^14.4 — ^13.4 || ^14.3 to support both. v11.5, v12.4 and v13.4 make 14.4 look like the next in line; it matches no release, so composer update fails dependency resolution, exits non-zero and installs nothing. Constraints for every version pair: references/upgrade-v13-to-v14.md
- Audit third-party dependencies for major version changes (consult
references/third-party-dependency-upgrades.md)
- Run
rector process --dry-run then review and apply
- Run
fractor process --dry-run then review and apply
- Run
php-cs-fixer fix
- Run
phpstan analyse against each supported dependency version and fix errors
- Run
phpunit and fix tests. Tests/ is part of the upgrade, not a
consequence of it. A class v14 removed, referenced from a test, is fatal
rather than failing: in an import, a parent, a property or a signature it
stops PHPUnit while it loads the suite, so nothing runs at all. Search for
the removed types across both trees before running anything:
grep -rnE 'TypoScriptFrontendController|StandaloneView|TemplateView|HashService|LocalPreviewHelper|LocalCropScaleMaskHelper|FreezableBackendInterface' Classes/ Tests/
Every hit is a fix. createMock on one of them cannot be repaired by
swapping the name — see references/upgrade-v13-to-v14.md
- Install the target version and run the suite against it. A green suite
on the version already installed proves nothing about the target — that is
the old code passing old tests. Install first, then test:
composer update "typo3/*" --with typo3/cms-core:^14.3 -W && vendor/bin/phpunit -c Build/phpunit/UnitTests.xml
The package argument matters: without it composer update moves every
dependency, and the test result then depends on upgrades that have nothing
to do with TYPO3. -W lets the TYPO3 packages' own dependencies follow.
- Verify success criteria (consult
references/verification.md)
Done means the suite passes with the target version installed. Not that the
constraint was widened, and not that the suite is green where it was already
green.
Where a removed class is referenced decides when it bites. In an import, a
parent class, a property or a signature it is resolved while PHPUnit loads
the suite, so nothing runs at all and the failure looks nothing like a test
failure. Referenced only inside a method body, it fails when that one test
executes, and the rest of the suite still passes — which is the more
comfortable failure and the easier one to miss in a summary line.
When the migration breaks the tests
It will. A suite that was green before Rector routinely comes back with dozens
of errors, and working through them is the job.
Never revert the migration to get back to green. Measured: an agent ran
Rector, saw Tests: 719, Errors: 34, discarded every migrated file under
Classes/, got OK (719 tests, 1176 assertions), and committed
composer.json, ext_emconf.php and two build files — no code at all. That
commit claims support for a version the code does not have, and it is the worst
of the three possible outcomes: a failing upgrade is visible, an unattempted one
is honest, and this one is neither.
Green after a revert is the state you started in. The only green that counts is
the one from step 10, with the target version installed and the migration in
place.
When NOT to Apply Automatically
Do NOT blindly apply Rector/Fractor when dual-version compatibility, missing
tests, unclear changes, or complex APIs (DBAL, Extbase) are involved. Instead
apply rules manually, testing between changes.
Third-Party Dependency Upgrades
When composer.json widens a dependency to a new major version: enumerate API usages, cross-reference the new API, verify mocks, use adapter pattern for signature differences, run PHPStan per major version. See references/third-party-dependency-upgrades.md.
Quick Commands
rector process --dry-run && rector process # PHP migrations
fractor process --dry-run && fractor process # Non-PHP migrations
php-cs-fixer fix && phpstan analyse && phpunit # Quality checks
Asset Templates
Config templates in assets/: rector.php, fractor.php, phpstan.neon, phpunit.xml, .php-cs-fixer.php
References
| Reference |
Use when... |
references/pre-upgrade.md |
Planning checklist, version audit, risk assessment |
references/api-changes.md |
Checking deprecated/removed APIs by TYPO3 version |
references/api-traps.md |
Cross-version footguns: TCA restrictions, boot order, DI bypass |
references/upgrade-v11-to-v12.md |
Upgrading from TYPO3 v11 to v12 |
references/upgrade-v12-to-v13.md |
Upgrading from TYPO3 v12 to v13 |
references/upgrade-v13-to-v14.md |
Upgrading from TYPO3 v13 to v14 |
references/dual-compatibility.md |
Dual compatibility (v12 + v13) |
references/real-world-patterns.md |
Real-world migration examples |
references/toolchain-output.md |
Rector/Fractor dry-run output |
references/troubleshooting.md |
Rector broke code, PHPStan errors, test failures |
references/third-party-dependency-upgrades.md |
Non-TYPO3 dependencies (major version bumps, adapter patterns) |
references/verification.md |
Success criteria and real-world testing |
references/multi-version-worktrees.md |
Per-LTS worktree layout, backport workflow, cross-version CI matrix |
references/audit-mode.md |
Assessing/estimating: ticket only non-automatable findings |
scripts/scan-deprecations.sh <path> |
Deterministic grep scan for deprecated/removed APIs and traps |
External Resources
1---2name: typo3-extension-upgrade-33description: Use when an extension has to work with a newer or the current TYPO3 LTS, when a version bump breaks compatibility or leaves deprecated APIs behind, when upgrading v11->v12, v12->v13 or v13->v14 (v14.3 LTS is the current target), when one codebase must stay compatible with two versions, when running Extension Scanner, Rector, Fractor or PHPStan against a target version, or when a specific v14 breaker bites - Fluid 5 strict ViewHelpers, HashService removal, the ext_tables.php split.4---56# TYPO3 Extension Upgrade Skill78Framework for upgrading TYPO3 extensions to newer LTS versions.9Extension code only, not project/core upgrades.1011## Upgrade Toolkit1213| Tool | Purpose | Files |14|------|---------|-------|15| Extension Scanner | Diagnose deprecated APIs | TYPO3 Backend |16| Rector | Automated PHP migrations | `.php` |17| Fractor | Non-PHP migrations | FlexForms, TypoScript, YAML, Fluid |18| PHPStan | Static analysis | `.php` |1920## Core Workflow21221. Complete planning phase (consult `references/pre-upgrade.md`)232. Create feature branch (verify git is clean)243. Update `composer.json` constraints for the target version. **v14's LTS minor is 3: write `^14.3`, never `^14.4`** — `^13.4 || ^14.3` to support both. v11.5, v12.4 and v13.4 make `14.4` look like the next in line; it matches no release, so `composer update` fails dependency resolution, exits non-zero and installs nothing. Constraints for every version pair: `references/upgrade-v13-to-v14.md`254. **Audit third-party dependencies** for major version changes (consult `references/third-party-dependency-upgrades.md`)265. Run `rector process --dry-run` then review and apply276. Run `fractor process --dry-run` then review and apply287. Run `php-cs-fixer fix`298. Run `phpstan analyse` **against each supported dependency version** and fix errors309. Run `phpunit` and fix tests. **`Tests/` is part of the upgrade, not a31 consequence of it.** A class v14 removed, referenced from a test, is fatal32 rather than failing: in an import, a parent, a property or a signature it33 stops PHPUnit while it loads the suite, so nothing runs at all. Search for34 the removed types across both trees before running anything:35 `grep -rnE 'TypoScriptFrontendController|StandaloneView|TemplateView|HashService|LocalPreviewHelper|LocalCropScaleMaskHelper|FreezableBackendInterface' Classes/ Tests/`36 Every hit is a fix. `createMock` on one of them cannot be repaired by37 swapping the name — see `references/upgrade-v13-to-v14.md`3810. **Install the target version and run the suite against it.** A green suite39 on the version already installed proves nothing about the target — that is40 the old code passing old tests. Install first, then test:41 `composer update "typo3/*" --with typo3/cms-core:^14.3 -W && vendor/bin/phpunit -c Build/phpunit/UnitTests.xml`42 The package argument matters: without it `composer update` moves every43 dependency, and the test result then depends on upgrades that have nothing44 to do with TYPO3. `-W` lets the TYPO3 packages' own dependencies follow.4511. Verify success criteria (consult `references/verification.md`)4647**Done means the suite passes with the target version installed.** Not that the48constraint was widened, and not that the suite is green where it was already49green.5051Where a removed class is referenced decides when it bites. In an `import`, a52parent class, a property or a signature it is resolved while PHPUnit *loads*53the suite, so nothing runs at all and the failure looks nothing like a test54failure. Referenced only inside a method body, it fails when that one test55executes, and the rest of the suite still passes — which is the more56comfortable failure and the easier one to miss in a summary line.5758## When the migration breaks the tests5960It will. A suite that was green before Rector routinely comes back with dozens61of errors, and working through them is the job.6263**Never revert the migration to get back to green.** Measured: an agent ran64Rector, saw `Tests: 719, Errors: 34`, discarded every migrated file under65`Classes/`, got `OK (719 tests, 1176 assertions)`, and committed66`composer.json`, `ext_emconf.php` and two build files — no code at all. That67commit claims support for a version the code does not have, and it is the worst68of the three possible outcomes: a failing upgrade is visible, an unattempted one69is honest, and this one is neither.7071Green after a revert is the state you started in. The only green that counts is72the one from step 10, with the target version installed and the migration in73place.7475## When NOT to Apply Automatically7677Do NOT blindly apply Rector/Fractor when dual-version compatibility, missing78tests, unclear changes, or complex APIs (DBAL, Extbase) are involved. Instead79apply rules manually, testing between changes.8081## Third-Party Dependency Upgrades8283When `composer.json` widens a dependency to a new major version: enumerate API usages, cross-reference the new API, verify mocks, use adapter pattern for signature differences, run PHPStan per major version. See `references/third-party-dependency-upgrades.md`.8485## Quick Commands8687```bash88rector process --dry-run && rector process # PHP migrations89fractor process --dry-run && fractor process # Non-PHP migrations90php-cs-fixer fix && phpstan analyse && phpunit # Quality checks91```9293## Asset Templates9495Config templates in `assets/`: `rector.php`, `fractor.php`, `phpstan.neon`, `phpunit.xml`, `.php-cs-fixer.php`9697## References9899| Reference | Use when... |100|-----------|-------------|101| `references/pre-upgrade.md` | Planning checklist, version audit, risk assessment |102| `references/api-changes.md` | Checking deprecated/removed APIs by TYPO3 version |103| `references/api-traps.md` | Cross-version footguns: TCA restrictions, boot order, DI bypass |104| `references/upgrade-v11-to-v12.md` | Upgrading from TYPO3 v11 to v12 |105| `references/upgrade-v12-to-v13.md` | Upgrading from TYPO3 v12 to v13 |106| `references/upgrade-v13-to-v14.md` | Upgrading from TYPO3 v13 to v14 |107| `references/dual-compatibility.md` | Dual compatibility (v12 + v13) |108| `references/real-world-patterns.md` | Real-world migration examples |109| `references/toolchain-output.md` | Rector/Fractor dry-run output |110| `references/troubleshooting.md` | Rector broke code, PHPStan errors, test failures |111| `references/third-party-dependency-upgrades.md` | Non-TYPO3 dependencies (major version bumps, adapter patterns) |112| `references/verification.md` | Success criteria and real-world testing |113| `references/multi-version-worktrees.md` | Per-LTS worktree layout, backport workflow, cross-version CI matrix |114| `references/audit-mode.md` | Assessing/estimating: ticket only non-automatable findings |115| `scripts/scan-deprecations.sh <path>` | Deterministic grep scan for deprecated/removed APIs and traps |116117## External Resources118119- [TYPO3 Rector](https://github.com/sabbelasichon/typo3-rector)120- [Fractor](https://github.com/andreaswolf/fractor)121- [TYPO3 Core Changelog](https://docs.typo3.org/c/typo3/cms-core/main/en-us/)