From: Tim Otten Date: Fri, 21 May 2021 18:51:32 +0000 (-0700) Subject: BAOs - Allow BAOs to subscribe to hooks/events via `EventSubscriberInterface` or... X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=c8d8465306767fe281283ed005f1f1cb86d0f7c1;p=civicrm-core.git BAOs - Allow BAOs to subscribe to hooks/events via `EventSubscriberInterface` or `HookInterface` Before: There is no pleasant way for a BAO to register a listener for an event. True, one can use `Civi::dispatch()`, but (lacking a good initialization point) it's hard to register reliably. True, you can also add new items to `\Civi\Core\Container::createEventDispatcher()`, but this is rather out-of-the-way. After: A BAO class may optionally implement `EventDispatcherInterface` or `HookInterface`. Methods will be automatically registered. The list of listeners will be cached in the container. --- diff --git a/CRM/Core/DAO/AllCoreTables.php b/CRM/Core/DAO/AllCoreTables.php index 0e4b38b848..04e4fe32dc 100644 --- a/CRM/Core/DAO/AllCoreTables.php +++ b/CRM/Core/DAO/AllCoreTables.php @@ -276,6 +276,23 @@ class CRM_Core_DAO_AllCoreTables { return array_values(self::daoToClass()); } + /** + * Get a list of all extant BAO classes. + * + * @return array + * Ex: ['Contact' => 'CRM_Contact_BAO_Contact'] + */ + public static function getBaoClasses() { + $r = []; + foreach (\CRM_Core_DAO_AllCoreTables::daoToClass() as $entity => $daoClass) { + $baoClass = str_replace('_DAO_', '_BAO_', $daoClass); + if (class_exists($baoClass)) { + $r[$entity] = $baoClass; + } + } + return $r; + } + /** * Get the classname for the table. * diff --git a/Civi/Core/Container.php b/Civi/Core/Container.php index 947a2657d8..fa723a77b3 100644 --- a/Civi/Core/Container.php +++ b/Civi/Core/Container.php @@ -1,6 +1,7 @@ addTag('kernel.event_subscriber')->setPublic(TRUE); } + $dispatcherDefn = $container->getDefinition('dispatcher'); + foreach (\CRM_Core_DAO_AllCoreTables::getBaoClasses() as $baoEntity => $baoClass) { + $listenerMap = EventScanner::findListeners($baoClass, $baoEntity); + if ($listenerMap) { + $file = (new \ReflectionClass($baoClass))->getFileName(); + $container->addResource(new \Symfony\Component\Config\Resource\FileResource($file)); + $dispatcherDefn->addMethodCall('addListenerMap', [$baoClass, $listenerMap]); + } + } + \CRM_Api4_Services::hook_container($container); \CRM_Utils_Hook::container($container);