--- /dev/null
+<?php
+
+namespace Civi\Shimmy\Mixins;
+
+/**
+ * Assert that the managed-entity mixin is working properly.
+ *
+ * This class defines the assertions to run when installing or uninstalling the extension.
+ * It use called as part of E2E_Shimmy_LifecycleTest.
+ *
+ * @see E2E_Shimmy_LifecycleTest
+ */
+class ManagedTest extends \PHPUnit\Framework\Assert {
+
+ public function testPreConditions($cv) {
+ $this->assertFileExists(static::getPath('/CRM/ShimmyGroup.mgd.php'), 'The shimmy extension must have a Menu XML file.');
+ }
+
+ public function testInstalled($cv) {
+ $items = $cv->api4('OptionGroup', 'get', ['where' => [['name', '=', 'shimmy_group']]]);
+ $this->assertEquals('Shimmy Group', $items[0]['title']);
+ $this->assertEquals(TRUE, $items[0]['is_active']);
+ }
+
+ public function testDisabled($cv) {
+ $items = $cv->api4('OptionGroup', 'get', ['where' => [['name', '=', 'shimmy_group']]]);
+ $this->assertEquals('Shimmy Group', $items[0]['title']);
+ $this->assertEquals(FALSE, $items[0]['is_active']);
+ }
+
+ public function testUninstalled($cv) {
+ $items = $cv->api4('OptionGroup', 'get', ['where' => [['name', '=', 'shimmy_group']]]);
+ $this->assertEmpty($items);
+ }
+
+ protected static function getPath($suffix = ''): string {
+ return dirname(__DIR__, 2) . $suffix;
+ }
+
+}
--- /dev/null
+<?php
+
+/**
+ * Auto-register "**.mgd.php" files.
+ *
+ * @mixinName mgd-php
+ * @mixinVersion 1.0.0
+ *
+ * @param CRM_Extension_MixInfo $mixInfo
+ * On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
+ * @param \CRM_Extension_BootCache $bootCache
+ * On newer deployments, this will be an instance of MixInfo. On older deployments, Civix may polyfill with a work-a-like.
+ */
+return function ($mixInfo, $bootCache) {
+
+ /**
+ * @param \Civi\Core\Event\GenericHookEvent $e
+ * @see CRM_Utils_Hook::managed()
+ */
+ Civi::dispatcher()->addListener('hook_civicrm_managed', function ($event) use ($mixInfo) {
+ // When deactivating on a polyfill/pre-mixin system, listeners may not cleanup automatically.
+ if (!$mixInfo->isActive()) {
+ return;
+ }
+
+ $mgdFiles = CRM_Utils_File::findFiles($mixInfo->getPath(), '*.mgd.php');
+ sort($mgdFiles);
+ foreach ($mgdFiles as $file) {
+ $es = include $file;
+ foreach ($es as $e) {
+ if (empty($e['module'])) {
+ $e['module'] = $mixInfo->longName;
+ }
+ if (empty($e['params']['version'])) {
+ $e['params']['version'] = '3';
+ }
+ $event->entities[] = $e;
+ }
+ }
+ });
+
+};