totten / civix

CiviCRM Extension Builder
http://civicrm.org/
Other
56 stars 56 forks source link

(dev/core#4999) Support Entity Framework v2 for extensions #331

Open totten opened 6 months ago

totten commented 6 months ago

Overview (Final)

Implement support for Entity Framework v2 (EFv2; aka dev/core#4999). This is a general overhaul of everything related to generate:entity. There's a more complete comparison of changes at: https://github.com/totten/civix/wiki/Entity-Templates

The PR was originally opened to address one major sub-problem (installation and SQL generation). I'm preserving that description so that the discussion remains intelligible. However, the ultimate scope of the PR evolved to cover more aspects of dev/core#4999 / EFv2. The wiki page gives a more comprehensive summation.


(Subject: Auto-generate SQL during installation via civimix-schema@5.72)

Overview (Original)

For extensions that use generate:entity / generate:entity-boilerplate, this changes the SQL lifecycle:

ping @colemanw @mattwire @artfulrobot @christianwach

Before

After

Related PRs

TODO

mattwire commented 6 months ago

Nice! @totten don't let this be a blocker but just wondering if the upgrade scenario has been considered? Where a new entity is added to already installed extension and needs to install that entity on upgrade. Maybe there is a function we can call from the upgrader?

colemanw commented 6 months ago

Maybe there is a function we can call from the upgrader?

I agree this would be beneficial. In the upgrade scenario you can't just read from the current schema and add that table as-is, because the table might change in the future, so your upgrader has to provide a snapshot of the table structure as it first appears. And we do want to leverage the goodness of the auto-detect-collation here. So a utility function would be great that you can feed in a table definition as an array and it spits out the CREATE TABLE sql.

totten commented 6 months ago

Thanks, good points about upgrading @mattwire @colemanw. (Aside: I got so far into the rabbit of hole of "how to polyfill an upgrader class" that I kind of stopped thinking about the design of the upgrader-class being delivered...)

Probably the most direct thing is like you say -- add a helper function. It feels like this means switching the class-relationship.

(I agree that adding the specific helper function probably shouldn't be a blocker. I'm not certain if it's easy or hard. But there should be a clear place to put that kind of helper.)


FWIW.... there's almost enough information to do updates like CREATE TABLE or ADD COLUMN automatically (without a named helper function) -- because the schema includes <add>NN</add> and <drop>NN</drop>. Obviously, other upgrade-steps - like filtering/modifying a column -- require richer definitions. That's why upgrade_NN() exists. Alas, the revision-sequences (the NN values) are different, and my brain would explode if <add>1.2</add> and upgrade_1002 were put in the same sequence.

I guess you could unify the sequences. Values like <add>1002</add> could be live upgrade instructions. (Equivalent to adding upgrade_1002() with an ALTER TABLE...ADD COLUMN... statement.) Values like <add>1.2</add> would have to be ignored somehow. (Ignore numbers less than 1000?...) The upshot is that you'd edit only one file for the basic case of adding new elements (without needing to copy-paste schema). And you could still define special upgrade-logic (filtering data; calling PHP code) via upgrade_NN().

I dunno, that sounds a little radical. For the moment, probably better to think about how to add helper function.

colemanw commented 6 months ago

... or to keep it very explicit: <autoAdd>1002</autoAdd>

totten commented 6 months ago

I've pushed a set of updates (but haven't updated description yet). Basically:

totten commented 4 months ago

civibot, test this please

totten commented 4 months ago

So I rebased and switched this from the unreleased civimix-schema@5.72 (XML-flavor schema helper) to the merged civimix-schema@5.74 (PHP-flavor schema helper). Quick take:

colemanw commented 3 months ago

@totten what's the status of this?

colemanw commented 3 months ago

@totten I've just finished converting the rest of our core extensions to use this.

totten commented 2 months ago

Ah, blerg. There's a test-interaction problem (i.e. tests pass individually but fail in bulk). E2E tests look like this:

   $this->civixGenerateModule(static::getKey(), [
      '--compatibility' => '5.69',
    ]);
    $this->civixGenerateUpgrader();
    $this->civixGenerateEntity('Bread');
    $this->civixGenerateEntity('Sandwich');

tldr: I need a separate PR to change the testing process.

colemanw commented 2 months ago

@totten this is looking good!