Skip to content

Commit

Permalink
Extensions - Reset container+dispatcher after toggling extensions
Browse files Browse the repository at this point in the history
This fixes an issue in E2E testing. Suppose you have a test like this:

  1: function testFoo() {
  2:   civicrm_api3('Extension', 'enable', ['key' => 'foo']);
  3:   assertTrue(Civi::container()->has('foo_service'));
  4:   civicrm_api3('Extension', 'disable', ['key' => 'foo']);
  5:   assertFalse(Civi::container()->has('foo_service'));
  6: }

The assertion at line 5 would fail -- because the 'disable' step did not
fully reset the `Container`.  This problem could then apply to anything that
lives in the container, such as the dispatcher and its listeners.

There is test-coverage in `mixin/scan-classes@1/example` and
`E2E_Shimmy_LifecycleTest::testLifecycleWithLocalFunctions()`.
The test doesn't specifically mention `Container`, but it focuses on one
important service (*the dispatcher*) that lives in the container.

I'm not sure if the problem affected headless tests.
  • Loading branch information
totten committed Aug 24, 2022
1 parent f5eb717 commit c76bdfc
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 3 deletions.
9 changes: 9 additions & 0 deletions CRM/Extension/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ public function replace($tmpCodeDir) {
}

$this->refresh();
// It might be useful to reset the container, but (given dev/core#3686) that's not likely to do much.
// \Civi::reset();
// \CRM_Core_Config::singleton(TRUE, TRUE);
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);
}

Expand Down Expand Up @@ -311,6 +314,8 @@ public function install($keys, $mode = 'install') {
$this->statuses = NULL;
$this->mapper->refresh();
if (!CRM_Core_Config::isUpgradeMode()) {
\Civi::reset();
\CRM_Core_Config::singleton(TRUE, TRUE);
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);

$schema = new CRM_Logging_Schema();
Expand Down Expand Up @@ -422,6 +427,8 @@ public function disable($keys) {

$this->statuses = NULL;
$this->mapper->refresh();
\Civi::reset();
\CRM_Core_Config::singleton(TRUE, TRUE);
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);

$this->popProcess($keys);
Expand Down Expand Up @@ -480,6 +487,8 @@ public function uninstall($keys) {

$this->statuses = NULL;
$this->mapper->refresh();
// At the analogous step of `install()` or `disable()`, it would reset the container.
// But here, the extension goes from "disabled=>uninstall". All we really need is to reconcile mgd's.
CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);
$this->popProcess($keys);
}
Expand Down
10 changes: 7 additions & 3 deletions Civi/Core/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,25 @@ public function loadContainer() {
return $containerBuilder;
}

$envId = \CRM_Core_Config_Runtime::getId();
$envId = md5(implode(',', array_merge(
[\CRM_Core_Config_Runtime::getId()],
array_column(\CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles(), 'prefix')
)));
$file = \Civi::paths()->getPath("[civicrm.compile]/CachedCiviContainer.{$envId}.php");
$containerCacheClass = "CachedCiviContainer_{$envId}";
$containerConfigCache = new ConfigCache($file, $cacheMode === 'auto');
if (!$containerConfigCache->isFresh()) {
$containerBuilder = $this->createContainer();
$containerBuilder->compile();
$dumper = new PhpDumper($containerBuilder);
$containerConfigCache->write(
$dumper->dump(['class' => 'CachedCiviContainer']),
$dumper->dump(['class' => $containerCacheClass]),
$containerBuilder->getResources()
);
}

require_once $file;
$c = new \CachedCiviContainer();
$c = new $containerCacheClass();
return $c;
}

Expand Down

0 comments on commit c76bdfc

Please sign in to comment.