Skip to content

[TASK] Guard SchemaMigrator::install() with applySafe() - #739

Merged
bmack merged 1 commit into
TYPO3:mainfrom
sbuerk:guard-schemamigrator-applysafe
Aug 10, 2026
Merged

[TASK] Guard SchemaMigrator::install() with applySafe()#739
bmack merged 1 commit into
TYPO3:mainfrom
sbuerk:guard-schemamigrator-applysafe

Conversation

@sbuerk

@sbuerk sbuerk commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

TYPO3 v15 reworks the database analyzer stack. As part of it, the internal
SchemaMigrator::install() is replaced by applySafe(): install() is kept as a
@deprecated thin wrapper for exactly one reason — this package creates the database
of every functional test through it — and is removed in a follow-up change.

Classes/Core/Testbase.php::createDatabaseStructure() is the only call site:

$schemaMigrationService->install($createTableStatements);

TYPO3 v14 only knows install(), and the main branch here supports
14.*.*@dev || 15.*.*@dev, so the call has to work against both.

Change

Call applySafe() when the migrator provides it, keep install() as the fallback:

// @todo: Remove the install() fallback when v14 compat is dropped, the
//        method no longer exists in v15.
if (method_exists($schemaMigrationService, 'applySafe')) {
    $schemaMigrationService->applySafe($createTableStatements);
    return;
}
$schemaMigrationService->install($createTableStatements);

Behaviour is unchanged on both sides: install() in v15 does nothing but delegate to
applySafe(), this call site never passed the v14 $createOnly argument, and the
return value was not evaluated before either.

Why a capability check and not a core version check

A Typo3Version check would be wrong here, not just less elegant. v15 nightlies and
every v15 dev state predating the analyzer rework report 15.x while still only having
install() — a version check would break them. method_exists() on the migrator
instance is true exactly when the call is valid.

method_exists() on the object is also preferred over class_exists() on one of the
new DTOs: the DTOs and applySafe() happen to land in the same core change today, but
the core side is a patch series still under review, and a split that introduces the
classes before the method would make a class_exists() probe return true one line
before a fatal. It follows the same shape as the existing
method_exists(Bootstrap::class, 'loadExtTables') guard a few lines above.

Verification

Run in this repository, all green:

PHP resolves suites
8.3 typo3/cms-core 14.3.x-dev (fallback branch) composerUpdate, cgl, lint, phpstan, unit
8.5 typo3/cms-core dev-main (v15) composerUpdate, lint, unit

No phpstan-baseline.neon entry is needed: $container->get() is PSR-11 and returns
mixed, so the probe is not statically resolvable and produces no
function.alreadyNarrowedType.

The TYPO3 Core functional suite result against this branch is added as a comment once
the corresponding core change has run through CI.

Coordination

This has to be merged and released before the core change that removes
SchemaMigrator::install() can be merged. The core side references this pull request in
its commit message.

TYPO3 v15 reworks the database analyzer stack and replaces the
internal SchemaMigrator::install() with applySafe(). install() is
deprecated in v15 and is removed there, while v14 only knows
install().

Call applySafe() when the migrator provides it and keep install()
as the fallback, so functional test databases are created on both
core versions.

The guard is a capability check and deliberately not a core version
check: v15 nightlies and every v15 dev state predating the rework
report v15 while still only having install(), so a version check
would break them.
@sbuerk

sbuerk commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

TYPO3 Core test results against this branch, as promised above.

The core side is a ten change relation chain on Gerrit under topic
database-analyzer, changes 95186 to 95195.
Its top change, 95195, removes
SchemaMigrator::install() and points typo3/testing-framework at this pull request branch, so the
whole chain is exercised against exactly this code.

All ten changes are Verified +1 by TYPO3 CI. That includes the e2e playwright composer jobs,
which build a real composer mode instance resolving typo3/testing-framework from this branch, and
the full functional matrix on sqlite, mariadb, mysql and postgres.

Locally, each of the ten commits was additionally checked out on its own and run through cgl,
phpstan, checkIntegrityPhp, checkRst, the license header check, unit Tests/Unit/Database +
Tests/Unit/Error and functional Tests/Functional/Database + Tests/Functional/Error on sqlite —
ten out of ten green. This matters for the guard specifically: commits 1 to 6 of that chain still
have only install(), commits 7 onwards have applySafe(), and commit 10 has install() removed.
One and the same vendored copy of this branch served all ten, taking the fallback in the first six
and the new call in the rest. That is the capability check doing its job across the whole range.

In this repository, on the branch itself: composerUpdate, cgl, lint, phpstan and unit pass
on PHP 8.3 (resolves typo3/cms-core 14.3.x-dev, exercising the install() fallback) and
composerUpdate, lint, unit pass on PHP 8.5 (resolves v15). No phpstan-baseline.neon entry was
needed.

Once this is merged and released, the core change raises the constraint from the branch to the
released version; it is explicitly blocked on that and cannot merge before.

@bmack
bmack merged commit 6cd6802 into TYPO3:main Aug 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants