Developer guide¶
Install dependencies¶
The extension carries its own composer.json; the vendor directory is
.Build/vendor.
Checks¶
composer ci:php:cs # PHP-CS-Fixer, PER-CS 2.0
composer fix:php:cs # ... and fix automatically
composer ci:php:stan # PHPStan level 8, no baseline
composer ci:tests:unit
composer ci:tests:functional
Functional tests need a database:
typo3DatabaseDriver=pdo_mysql \
typo3DatabaseHost=db typo3DatabasePort=3306 \
typo3DatabaseUsername=root typo3DatabasePassword=root \
typo3DatabaseName=func_aimark \
composer ci:tests:functional
Accessibility tests (Playwright + axe-core, WCAG 2.1 AA):
They run against a static fixture at
Tests/Acceptance/fixtures/labelled-page.html and therefore need neither a
database nor a TYPO3 boot. So that this proves something, the functional test
MarkupFixtureTest checks that the fixture still contains exactly the markup
LabelRenderService produces — change the Fluid template and it fails until
the fixture follows.
The fixture is served by a small Node server (Tests/Acceptance/server.mjs),
not over file://: browsers refuse to load ES modules from file://, the
page would come up without its JavaScript, and the keyboard tests would pass
for the wrong reason.
CLI¶
vendor/bin/typo3 aimark:scan --dry-run --limit=50
vendor/bin/typo3 aimark:scan --storage=1 --force
vendor/bin/typo3 aimark:report --limit=25 --email=editors@example.com
vendor/bin/typo3 aimark:verify --dry-run
All three are schedulable. --force on the scan refreshes existing
suggestions and leaves confirmed records alone — detection may not overrule a
person, whatever options it is given.
Conventions¶
- Code style: PER-CS 2.0 (
(int) $valuewith a space). It differs from the TYPO3 CGL but is what CI enforces — do not write against it. - Language: classes, variables and comments in English. Labels and the German documentation in German.
- XLIFF:
locallang*.xlfis the English source language,de.locallang*.xlfthe translation. That is the TYPO3 convention; a file nameden.locallang*.xlfwould never be loaded, since TYPO3 resolvesenas the default language. - Comments explain the why, not the what.
- No XCLASS overrides, no deprecated core API.
Pitfalls already encountered¶
displayCondis evaluated server-side only in TYPO3 v14. Dependent fields appear after saving, not while choosing in the form.- Tables without TCA get no
uidand no primary key from the schema migrator.tx_ntaimark_audittherefore declares both explicitly inext_tables.sql. EXT:paths are not resolvable in unit tests, because no package is registered.IconResolverServicetherefore takes its directory through the constructor.- Fluid's
f:translateneeds the request attributesapplicationType(as anint, not an enum case),siteandlanguage. Functional tests have to build such a request. - Fluid resolves
{item.labelKey}throughgetLabelKey(). An enum method namedlabelKey()renders as empty rather than failing, so values are prepared in PHP instead of handing enums to the template. - Backend controllers need the
#[AsController]attribute; DataHandler hooks needpublic: true, because they are created throughmakeInstance. - An exception inside a DataHandler hook aborts the whole save. The audit call is wrapped for that reason: a gap in the trail is bad, an editor who cannot save at all is worse.
Release¶
Before the tag:
- Set the version in
ext_emconf.php. - Add to
CHANGELOG.mdunder the concrete version number — do not collect under[Unreleased]. - Update the affected documentation.
Then:
.github/workflows/publish-ter.yml takes over. It runs code style, static
analysis and unit tests first, then checks that the version in
ext_emconf.php matches the tag and that CHANGELOG.md has an entry for it,
and only then publishes through typo3/tailor.
Once, before the first release¶
| Step | Where |
|---|---|
Reserve the extension key nt_aimark |
https://extensions.typo3.org/ |
| Create an access token (scope "Extension write") | TYPO3 account → Access Tokens |
Store it as the secret TYPO3_API_TOKEN |
GitHub → Settings → Secrets and variables → Actions |
Without the secret the workflow stops with a clear message rather than quietly doing nothing.
Known notices¶
TYPO3 14.3 deprecates ext_emconf.php. The file stays as long as TYPO3 13.4
is supported. The notice appears when the package artifact is built, not on
every request.