Skip to content

Instantly share code, notes, and snippets.

@totten

totten/index.md Secret

Last active February 1, 2020 02:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save totten/cdcf5542911052322003db7a8ba16b0a to your computer and use it in GitHub Desktop.
Save totten/cdcf5542911052322003db7a8ba16b0a to your computer and use it in GitHub Desktop.
Protocol for toggled autoloader

Background

  • It is already common for extensions to include a composer.json and to commit a vendor/ 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.

General Approach

Update the code-convention for an extension so that it can be used in either style:

  1. The extension is its own project root which must load its own vendor/autoload.php.
  2. 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.

Specific Approach

Define a CiviCRM setting to specify how to use the autoloader -- e.g.

  1. If each extension is independent: cv api setting.create composerAutoload=independent
  2. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment