- It is already common for extensions to include a
composer.json
and to commit avendor/
tree. - This is done because it is easy and often works.
- It is also problematic in the long-term - because the dependency-resolver cannot reconcile requirements of different extensions. Conflicts play out at runtime.
- Changing the long-term issue requires that each site have some "root" project into which various extensions are added. But that is an invasive change.
Update the code-convention for an extension so that it can be used in either style:
- The extension is its own project root which must load its own
vendor/autoload.php
. - The extension is a dependency which can assume that someone else has loaded the
vendor/autoload.php
Today, an extension written for style #1 might say:
function example_civicrm_config(&$config) {
require_once __DIR__ . '/vendor/autoload.php';
// ...
}
An extension for style #2 would have nothing of the sort.
To support both styles, one needs some kind of conditionality.
Define a CiviCRM setting to specify how to use the autoloader -- e.g.
- If each extension is independent:
cv api setting.create composerAutoload=independent
- If all extensions are loaded together:
cv api setting.create composerAutoload=global
The boilerplate in the extension (perhaps defined via civix) would check this setting:
function example_civicrm_config(&$config) {
$al = Civi::settings()->get('composerAutoload');
if (!$al || $al === 'independent') {
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php';
}
}
// ...
}
The default composerAutoload
would likely be tuned somewhere -- e.g. D7 sites should default to composerAutoload=independent
and D8 to composerAutoload=global
.