Import the base upgrader
Overview
Many extensions include an "upgrader", "base upgrader" class, and wiring to support them. This patch migrates a lot of that boilerplate to core and does some cleanup in the process.
Current behavior
Most extensions which define schema rely on civix
's upgrader template. It defines these four elements:
-
myext.php
: This has stubs forhook_install
,hook_uninstall
,hook_upgrade
, etc -- each delegates tomyext.civix.php
. -
myext.civix.php
: This has stubs forhook_install
,hook_uninstall
,hook_upgrade
, etc -- each delegates toCRM/Myext/Upgrader.php
. -
CRM/Myext/Upgrader.php
: This is the customizable list of install/uninstall/upgrade steps. -
CRM/Myext/Upgrader/Base.php
: This is a large boilerplate file. It has a library of helpers+adapters.
Proposed behavior
Going forward, core extensions (and future civix-based extensions) will only define two elements:
-
info.xml
: Declare<upgrader>CRM_Myext_Upgrader</upgrader>
. -
CRM/Myext/Upgrader.php
: As before, this is the customizable list of install/uninstall/upgrade steps. It implements an interface (CRM_Extension_Upgrader_Interface
). For convenience, it can extend the base implementation (CRM_Extension_Upgrader_Base
) which matches the old boilerplate.
Comments
This is not an end in itself -- it is a step toward a few other things:
- For #2518 (closed) - We'd like to enqueue upgrade tasks in topological order. One way to do that is to control the order of dispatch for
hook_upgrade
. But in the current regime, we don't have enough control over the order in whichhook_upgrade
fires. - For https://github.com/totten/civix/issues/175 - We'd like to dedupe some of the civix boilerplate. https://github.com/civicrm/civicrm-core/pull/19865/ gets a long way there -- but only for runtime hooks (
hook_xmlMenu
,hook_managed
, ad nauseum). Lifecycle hooks (hook_install
,hook_uninstall
, etc) are special/non-standard.
There's a common theme in those -- the old way of wiring-up lifecycle-hooks is problematic, and making a direct change is also problematic. This approach will provide alternate wiring for the lifecycle-hooks.
Note that this change does not require any hard-breaks:
- Existing extensions can still use all the same boilerplate and wiring, and they will behave the same way.
- The new arrangement only takes effect when you define the
<upgrader>
tag. (civix
will be responsible for encouraging a transition.) - When you do add the
<upgrader>
tag, you can remove a bunch of boilerplate, but the main substance (CRM_Myext_Upgrader
) does not need any change. It supports the same methods as before (e.g.upgrade_NNNN()
,executeSql()
,addTask()
, etc).
And a few final tidbits:
- This gives an opportunity to do a bit of cleanup in the upgrader code (e.g. extracting logical
trait
s). - As before, it is still possible for an extension to completely reorganize its upgrade functionality (e.g. splitting out steps as separate files or using named-steps instead of numbered-steps).