Skip to content

IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL)#785

Draft
Steveb-p wants to merge 4 commits into
4.6from
doctrine-migrations-installer-inline-sql
Draft

IBX-11939: [Doctrine Migrations] Added Doctrine Migrations-based schema and data install path (inlined SQL)#785
Steveb-p wants to merge 4 commits into
4.6from
doctrine-migrations-installer-inline-sql

Conversation

@Steveb-p

@Steveb-p Steveb-p commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
Question Answer
JIRA issue IBX-11939
Type feature
Target Ibexa version v4.6
BC breaks no

Alternative to #784, using the same IbexaMigrationInterface + IbexaMigrationTag + TaggedMigrationsRunner/IbexaOnlyDependencyFactory mechanism, but with InstallSchemaMigration/ImportDataMigration implemented as plain Doctrine\Migrations\AbstractMigration subclasses with all SQL inlined directly in PHP (via addSql()), instead of Ibexa's AbstractVersion + YAML manifest + one-SQL-statement-per-file mechanism. This drops the 509 generated YAML/SQL resource files in favor of two self-contained PHP migration classes.

Adds an ibexa/doctrine-migrations-based alternative to the event-driven SchemaBuilderEvent mechanism CoreInstaller currently uses to install the core schema and bootstrap data, controlled by a new ibexa.installer.schema_builder_event.enabled setting (defaults to true, preserving current behavior).

  • Enabled (default): CoreInstaller keeps dispatching SchemaBuilderEvent and importing cleandata.sql directly - unchanged.
  • Disabled: schema creation and data import are each modeled as a Doctrine migration (InstallSchemaMigration, ImportDataMigration), tagged with IbexaMigrationTag for discovery, and executed via TaggedMigrationsRunner through IbexaOnlyDependencyFactory - an independent Doctrine Migrations DependencyFactory scoped to only Ibexa-tagged migrations, so a project's own migrations are never accidentally picked up. Each migration's execution is recorded in the standard Doctrine Migrations versioning table, making repeated installs idempotent.

InstallSchemaMigration's SQL (mysql/postgresql/sqlite) is generated from the existing schema.yaml; ImportDataMigration's SQL is generated from the existing per-DBMS cleandata.sql files, with the mysql statements also reused verbatim for sqlite (which previously had no cleandata support at all). Long or naturally multi-line statements (CREATE TABLE, multi-row INSERT, long ALTER TABLE ... ADD CONSTRAINT) use PHP NOWDOC for readability; verified byte-for-byte equivalent (aside from whitespace) to the SQL produced by #784.

Requires ibexa/doctrine-migrations (currently tracked via its feat/doctrine-migrations branch, added as a VCS repository).

Checklist:

  • Provided PR description.
  • Tested the solution manually.
  • Provided automated test coverage.
  • Checked that target branch is set correctly (main for features, the oldest supported for bugs).
  • Ran PHP CS Fixer for new PHP code (use $ composer fix-cs).
  • Asked for a review (ping @ibexa/engineering).

Steveb-p added 4 commits July 16, 2026 17:41
… install path

Adds an ibexa/doctrine-migrations-based alternative to the event-driven
SchemaBuilderEvent mechanism CoreInstaller has used to install the core
schema and bootstrap data. Controlled by the new
"ibexa.installer.schema_builder_event.enabled" setting (defaults to true,
preserving current behavior):

- When enabled (default), CoreInstaller keeps dispatching
  SchemaBuilderEvent and importing cleandata.sql directly, unchanged.
- When disabled, schema creation and data import are each modeled as an
  AbstractVersion migration (InstallSchemaMigration, ImportDataMigration),
  tagged for discovery, and executed via TaggedMigrationsRunner through
  the new IbexaOnlyDependencyFactory service - an independent Doctrine
  Migrations DependencyFactory scoped to only Ibexa-tagged migrations, so
  a project's own migrations are never accidentally executed. Each
  migration's execution is recorded in the standard Doctrine Migrations
  versioning table, making repeated installs idempotent.

InstallSchemaMigration's SQL (mysql/postgresql/sqlite, one statement per
file) is generated from the existing schema.yaml; ImportDataMigration's
from the existing per-DBMS cleandata.sql files (with the mysql statements
reused verbatim for sqlite, which previously had no cleandata support at
all).
Symfony\Component\DependencyInjection\ServiceLocator is not a generic
class, so PHPStan rejects the ServiceLocator<Installer> PHPDoc type used
for InstallPlatformCommand::$installers. Removed the invalid generic
parameter; the type-hint itself (plain ServiceLocator) is unaffected.
Converts InstallSchemaMigration and ImportDataMigration from
Ibexa\Contracts\DoctrineMigrations\Migrations\AbstractVersion (which loads
its SQL from a YAML manifest + one-statement-per-file pairs at runtime) to
Doctrine\Migrations\AbstractMigration directly, with every statement
inlined as an addSql() call in up(), branching on $this->platform
(MySqlPlatform/PostgreSqlPlatform/SqlitePlatform).

Both still implement IbexaMigrationInterface and are tagged with
IbexaMigrationTag::TAG in services.yml, so they remain discoverable by
TaggedMigrationsRunner/ServiceMigrationsRepository/IbexaOnlyDependencyFactory
exactly as before - no other part of the installer changes.

Removes the entire Resources/migrations/ YAML+SQL-file tree (509 files),
generated from the same schema.yaml/cleandata.sql sources as before.
CREATE TABLE statements are now pretty-printed one column per line, and
other long or naturally multi-line statements (multi-row INSERT, long
ALTER TABLE ... ADD CONSTRAINT) use NOWDOC instead of a single escaped
string literal, for readability. SQL content is unchanged.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
89.9% Duplication on New Code (required ≤ 3%)
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

💡 Need a hand with PR review? Try Gitar by Sonar!

@Steveb-p

Copy link
Copy Markdown
Contributor Author

Companion PR in ibexa/installer, adjusting AbstractProductInstaller for CoreInstaller's new constructor arguments: ibexa/installer#213

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.

1 participant