Claude
Skills
Sign in
Back

typo3-batch

Included with Lifetime
$97 forever

Plans and executes batch TYPO3 migrations and large-scale refactors across hooks, PSR-14 events, TCA, dependency injection, Fluid, namespaces, ext_localconf, Content Blocks, localization, and PHP upgrades. Use when the user asks for bulk migration, mass refactor, codemod-style TYPO3 updates, repeated fixes across an extension, or coordinated v14 modernization.

Writing & Docs

What this skill does

# TYPO3 Batch Operations

> Source: https://github.com/dirnbauer/webconsulting-skills

> Adapted from Boris Cherny's (Anthropic) Claude Code `/batch` skill for TYPO3 contexts.
> **Target:** TYPO3 v14.x only.

Orchestrate large-scale, parallelizable changes across a TYPO3 codebase. Decompose work
into 5–30 independent units, present a plan, then execute each unit with verification.

## Process

1. **Research**: Scan codebase to find all affected files
2. **Decompose**: Split work into independent, non-conflicting units
3. **Plan**: Present numbered plan to user for approval
4. **Execute**: Apply each unit, run verification after each
5. **Report**: Summarize changes, list any failures

## Execution Rules

- Each unit must be independently verifiable
- Never modify the same file in two different units
- Run `composer normalize` / `php -l` / PHPStan after PHP changes
- Run tests if available (`vendor/bin/phpunit`)
- Commit each unit separately with descriptive message
- Stop and report if a unit breaks tests

## Common TYPO3 Batch Operations

### 1. Hook → PSR-14 Event Migration

**Research**: Find all entries in `$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']` and
`$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']`.

**Decompose**: One unit per hook class.

**Per unit:**

```
1. Identify the hook interface/method
2. Find the corresponding PSR-14 event (see mapping below)
3. Create new event listener class with #[AsEventListener]
4. Move logic from hook method to __invoke()
5. Remove hook registration from ext_localconf.php
6. If **not** using `#[AsEventListener]`: register the listener in `Services.yaml`. With the attribute and `autoconfigure: true` (default), no extra `tags:` entry is required.
7. Run php -l on new file
```

**Hook → event mapping (verify in [Core event lists](https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Events/Events/Index.html)):**

> **DataHandler (`t3lib/class.t3lib_tcemain.php`):** TYPO3 Core does **not** expose generic PSR-14 events named like `BeforeRecordOperationEvent` / `AfterRecordOperationEvent` under `TYPO3\CMS\Core\DataHandling\Event`. For datamap/cmdmap reactions, use **`SC_OPTIONS` hook classes** (see [typo3-datahandler](../typo3-datahandler/SKILL.md) §9). Do not “migrate” those hooks to non-existent events.

| Hook / legacy API | Typical direction |
|---|---|
| `processDatamap_afterDatabaseOperations` / related `SC_OPTIONS` | Keep **`processDatamapClass`** hook methods (no 1:1 Core event) |
| `processDatamap_preProcessFieldArray` | Keep hook or narrow Core events for your table/field if documented |
| `processCmdmap_postProcess` | Keep **`processCmdmapClass`** hook methods |
| `drawHeaderHook` | `ModifyButtonBarEvent` |
| `drawFooterHook` | `ModifyButtonBarEvent` |
| `checkFlexFormValue` | Still often a hook; **`AfterFlexFormDataStructureParsedEvent`** is for DS parsing, not a drop-in for validation — confirm in Core for your case |
| `PageRenderer` render hooks (`render-preProcess`, `render-postProcess`) | No 1:1 PSR-14 replacement; prefer PSR-15 middleware for render-pipeline manipulation |
| `tslib_fe->contentPostProc` (cached) | `AfterCacheableContentIsGeneratedEvent` |
| `tslib_fe->contentPostProc` (output) | `AfterCachedPageIsPersistedEvent` — verify name in Core for your TYPO3 version |
| `tslib_fe->contentPostProc` (all) | No single PSR-14 replacement — split by what the hook actually does |
| `BackendUtility->getPagesTSconfig` | `ModifyLoadedPageTsConfigEvent` |
| `generatePageTSconfig` | `ModifyLoadedPageTsConfigEvent` |

**Not 1:1 replacements (verify before batch-rewriting):**

- **`drawHeaderHook` / `drawFooterHook`** — Legacy backend doc-header integration points. `ModifyButtonBarEvent` covers the **button bar** only; full header/footer chrome may need a different Core event or a documented alternative for your module type.
- **`tslib_fe->contentPostProc`** — Sub-hooks (`all`, `cached`, `output`) run at different FE pipeline stages. Map **cached** → `AfterCacheableContentIsGeneratedEvent`, **output** → `AfterCachedPageIsPersistedEvent` where applicable; **`all`** has no drop-in event — re-check Core docs.

### 2. TCA modernization (cumulative toward v14 target)

**Research**: Scan all `Configuration/TCA/` and `Configuration/TCA/Overrides/` files.

**Decompose**: One unit per TCA file.

**Per unit:**

```
1. Replace 'eval' => 'required' → 'required' => true
2. Replace 'eval' => 'trim' → keep where trimming is desired (trim is NOT applied by default)
3. Replace 'eval' => 'null' → 'nullable' => true
4. Replace 'eval' => 'int' → 'type' => 'number'
5. Replace 'renderType' => 'inputDateTime' → 'type' => 'datetime'
6. Replace 'renderType' => 'inputLink' → 'type' => 'link'
7. Replace 'renderType' => 'colorPicker' → 'type' => 'color'
8. Replace 'type' => 'input', 'eval' => 'email' → 'type' => 'email'
9. Convert items arrays: [0] => label, [1] => value → ['label' => ..., 'value' => ...]
10. Remove boilerplate columns auto-created from `ctrl` on TYPO3 v14: hidden, starttime, endtime, fe_group, language fields
11. Use palettes for enablecolumns: visibility → hidden, access → starttime, endtime
12. Remove convention fields from ext_tables.sql (auto-added to database)
13. Run php -l to verify syntax
```

### 3. GeneralUtility::makeInstance → DI

**Research**: Find all `GeneralUtility::makeInstance()` calls in Classes/.

**Decompose**: One unit per class file.

**Per unit:**

```
1. Identify all makeInstance calls in the class
2. For each: add constructor parameter with type
3. Replace makeInstance calls with $this->propertyName
4. Add/update Services.yaml if needed
5. Use readonly promoted properties
6. Verify with php -l
```

### 4. Fluid Template Refactoring

**Research**: Scan `Resources/Private/Templates/`, `Partials/`, `Layouts/`.

**Decompose**: One unit per template directory or logical group.

**Per unit:**

```
1. Replace hardcoded strings with <f:translate> keys
2. Add missing XLIFF entries to locallang.xlf
3. Replace <a href="..."> with <f:link.page> or <f:link.typolink>
4. Replace <img> with <f:image>
5. Extract repeated blocks to Partials
6. Add accessibility attributes (alt, aria-label, role)
```

### 5. Namespace Rename / Extension Key Change

**Research**: Find all files containing old namespace/extension key.

**Decompose**: Group by file type (PHP, Fluid, YAML, TypoScript, SQL).

**Per unit:**

```
PHP files:
  1. Replace namespace declarations
  2. Replace use statements
  3. Replace class references in strings (DI, TCA)
  
Fluid files:
  1. Replace {namespace} declarations
  2. Replace ViewHelper references
  
Configuration files:
  1. Update composer.json autoload
  2. Update ext_emconf.php
  3. Update Services.yaml service names
  4. Update TCA table prefixes
  5. Update TypoScript paths (EXT:old → EXT:new)
  
Database:
  1. Generate SQL rename migration
  2. Update ext_tables.sql
```

### 6. ext_localconf / ext_tables Cleanup

**Research**: Scan `ext_localconf.php` and `ext_tables.php` for movable code.

**Decompose**: One unit per concern (TSconfig, TypoScript, icons, modules, plugins).

**Per unit:**

```
Page TSconfig:
  1. Extract addPageTSConfig() calls
  2. Create Configuration/page.tsconfig
  3. Remove from ext_localconf.php

User TSconfig:
  1. Extract addUserTSConfig() calls  
  2. Create Configuration/user.tsconfig
  3. Remove from ext_localconf.php

Icons:
  1. Extract icon registry calls
  2. Move to Configuration/Icons.php (v14)
  3. Remove from ext_localconf.php

Backend modules:
  1. Extract registerModule() calls
  2. Move to Configuration/Backend/Modules.php
  3. Remove from ext_tables.php
```

### 7. Test Infrastructure Setup

**Research**: Check if `Tests/` directory exists, find testable classes.

**Decompose**: One unit per test type.

**Per unit:**

```
Unit tests:
  1. Create Tests/Unit/ structure
  2. Generate test class per service/utility class
  3. Add phpunit.xml.dist configuration
  
Functional tests:
  1. Create Tests/Functional/ structure
  2. Add fixt

Related in Writing & Docs