From 0d0031a0697bac23339f2a04c9801ab6035c282c Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Thu, 13 Apr 2017 19:25:44 -0700 Subject: [PATCH] CiviEventInspector - Include metadata about some non-hook events --- Civi/API/Events.php | 12 +++++ Civi/Core/CiviEventInspector.php | 45 +++++++++++++++---- Civi/Core/Container.php | 3 ++ Civi/Core/Event/SystemInstallEvent.php | 8 ++++ .../Civi/Core/CiviEventInspectorTest.php | 4 +- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/Civi/API/Events.php b/Civi/API/Events.php index 1dd7349278..0faa4502fa 100644 --- a/Civi/API/Events.php +++ b/Civi/API/Events.php @@ -105,4 +105,16 @@ class Events { ); } + /** + * @param \Civi\Core\Event\GenericHookEvent $e + * @see \CRM_Utils_Hook::hooks + */ + public static function hookEventDefs($e) { + $e->inspector->addEventClass(self::AUTHORIZE, 'Civi\API\Event\AuthorizeEvent'); + $e->inspector->addEventClass(self::EXCEPTION, 'Civi\API\Event\ExceptionEvent'); + $e->inspector->addEventClass(self::PREPARE, 'Civi\API\Event\PrepareEvent'); + $e->inspector->addEventClass(self::RESOLVE, 'Civi\API\Event\ResolveEvent'); + $e->inspector->addEventClass(self::RESPOND, 'Civi\API\Event\RespondEvent'); + } + } diff --git a/Civi/Core/CiviEventInspector.php b/Civi/Core/CiviEventInspector.php index f4dc1c6e2a..769d2f393d 100644 --- a/Civi/Core/CiviEventInspector.php +++ b/Civi/Core/CiviEventInspector.php @@ -77,7 +77,7 @@ class CiviEventInspector { */ public function find($regex) { $this->build(); - return array_filter($this->eventDefs, function($e) use ($regex) { + return array_filter($this->eventDefs, function ($e) use ($regex) { return preg_match($regex, $e['name']); }); } @@ -101,11 +101,21 @@ class CiviEventInspector { * TRUE if valid. */ public function validate($eventDef) { - return - is_array($eventDef) - && !empty($eventDef['name']) - && isset($eventDef['signature']) - && is_array($eventDef['fields']); + if (!is_array($eventDef) || empty($eventDef['name']) || !isset($eventDef['type'])) { + return FALSE; + } + + if (!in_array($eventDef['type'], array('hook', 'object'))) { + return FALSE; + } + + if ($eventDef['type'] === 'hook') { + if (!isset($eventDef['signature']) || !is_array($eventDef['fields'])) { + return FALSE; + } + } + + return TRUE; } /** @@ -117,11 +127,11 @@ class CiviEventInspector { public function add($eventDef) { $name = isset($eventDef['name']) ? $eventDef['name'] : NULL; - if (!isset($eventDef['is_hook'])) { - $eventDef['is_hook'] = (bool) preg_match('/^hook_/', $eventDef['name']); + if (!isset($eventDef['type'])) { + $eventDef['type'] = preg_match('/^hook_/', $eventDef['name']) ? 'hook' : 'object'; } - if (empty($eventDef['signature'])) { + if ($eventDef['type'] === 'hook' && empty($eventDef['signature'])) { $eventDef['signature'] = implode(', ', array_map( function ($field) { $sigil = $field['ref'] ? '&$' : '$'; @@ -139,6 +149,23 @@ class CiviEventInspector { return $this; } + /** + * Scan a Symfony event class for metadata, and add it. + * + * @param string $event + * Ex: 'civi.api.authorize'. + * @param string $className + * Ex: 'Civi\API\Event\AuthorizeEvent'. + * @return CiviEventInspector + */ + public function addEventClass($event, $className) { + $this->add(array( + 'name' => $event, + 'class' => $className, + )); + return $this; + } + /** * Scan a class for hook stubs, and add all of them. * diff --git a/Civi/Core/Container.php b/Civi/Core/Container.php index 1dcd8a8969..f369580a03 100644 --- a/Civi/Core/Container.php +++ b/Civi/Core/Container.php @@ -251,6 +251,9 @@ class Container { $dispatcher->addListener('hook_civicrm_caseChange', array('\Civi\CCase\Events', 'delegateToXmlListeners')); $dispatcher->addListener('hook_civicrm_caseChange', array('\Civi\CCase\SequenceListener', 'onCaseChange_static')); $dispatcher->addListener('hook_civicrm_hooks', array('\Civi\Core\CiviEventInspector', 'findBuiltInEvents')); + // TODO We need a better code-convention for metadata about non-hook events. + $dispatcher->addListener('hook_civicrm_hooks', array('\Civi\API\Events', 'hookEventDefs')); + $dispatcher->addListener('hook_civicrm_hooks', array('\Civi\Core\Event\SystemInstallEvent', 'hookEventDefs')); $dispatcher->addListener('civi.dao.postInsert', array('\CRM_Core_BAO_RecurringEntity', 'triggerInsert')); $dispatcher->addListener('civi.dao.postUpdate', array('\CRM_Core_BAO_RecurringEntity', 'triggerUpdate')); $dispatcher->addListener('civi.dao.postDelete', array('\CRM_Core_BAO_RecurringEntity', 'triggerDelete')); diff --git a/Civi/Core/Event/SystemInstallEvent.php b/Civi/Core/Event/SystemInstallEvent.php index 64858020f7..7957fd96a3 100644 --- a/Civi/Core/Event/SystemInstallEvent.php +++ b/Civi/Core/Event/SystemInstallEvent.php @@ -38,4 +38,12 @@ class SystemInstallEvent extends \Symfony\Component\EventDispatcher\Event { */ const EVENT_NAME = 'civi.core.install'; + /** + * @param \Civi\Core\Event\GenericHookEvent $e + * @see \CRM_Utils_Hook::hooks + */ + public static function hookEventDefs($e) { + $e->inspector->addEventClass(self::EVENT_NAME, __CLASS__); + } + } diff --git a/tests/phpunit/Civi/Core/CiviEventInspectorTest.php b/tests/phpunit/Civi/Core/CiviEventInspectorTest.php index 36482f13f1..6997d9618c 100644 --- a/tests/phpunit/Civi/Core/CiviEventInspectorTest.php +++ b/tests/phpunit/Civi/Core/CiviEventInspectorTest.php @@ -12,7 +12,8 @@ class CiviEventInspectorTest extends \CiviUnitTestCase { $eventDef = $inspector->get('hook_civicrm_alterSettingsMetaData'); $this->assertEquals('hook_civicrm_alterSettingsMetaData', $eventDef['name']); $this->assertEquals(array('settingsMetaData', 'domainID', 'profile'), array_keys($eventDef['fields'])); - $this->assertTrue($eventDef['is_hook']); + $this->assertEquals('hook', $eventDef['type']); + $this->assertNotEmpty($eventDef['description_html']); $this->assertTrue($eventDef['fields']['settingsMetaData']['ref']); $this->assertFalse($eventDef['fields']['domainID']['ref']); $this->assertEquals('&$settingsMetaData, $domainID, $profile', $eventDef['signature']); @@ -26,7 +27,6 @@ class CiviEventInspectorTest extends \CiviUnitTestCase { $this->assertTrue(isset($all['hook_civicrm_alterSettingsMetaData'])); foreach ($all as $name => $eventDef) { $this->assertEquals($name, $eventDef['name']); - $this->assertNotEmpty($eventDef['description_html']); $this->assertTrue($inspector->validate($eventDef)); } } -- 2.25.1