From 378e2654b9f389f315fcf6a0c51ce649e7866971 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Sat, 10 May 2014 21:54:06 -0700 Subject: [PATCH] CRM-14478 - ManagedEntities - Add support for 'cleanup' policy ("unused") --- CRM/Core/ManagedEntities.php | 26 ++++++- Civi/Core/Container.php | 5 +- api/v3/Generic.php | 7 +- .../phpunit/CRM/Core/ManagedEntitiesTest.php | 69 +++++++++++++++++++ 4 files changed, 103 insertions(+), 4 deletions(-) diff --git a/CRM/Core/ManagedEntities.php b/CRM/Core/ManagedEntities.php index 1aca464609..fd97edb3a9 100644 --- a/CRM/Core/ManagedEntities.php +++ b/CRM/Core/ManagedEntities.php @@ -53,6 +53,8 @@ class CRM_Core_ManagedEntities { /** * Read the managed entity + * + * @return array|NULL API representation, or NULL if the entity does not exist */ public function get($moduleName, $name) { $dao = new CRM_Core_DAO_Managed(); @@ -242,7 +244,29 @@ class CRM_Core_ManagedEntities { */ public function removeStaleEntity($dao) { $policy = empty($dao->cleanup) ? 'always' : $dao->cleanup; - $doDelete = ($policy == 'always'); + switch ($policy) { + case 'always': + $doDelete = TRUE; + break; + case 'never': + $doDelete = FALSE; + break; + case 'unused': + $getRefCount = civicrm_api3($dao->entity_type, 'getrefcount', array( + 'debug' => 1, + 'id' => $dao->entity_id + )); + + $total = 0; + foreach ($getRefCount['values'] as $refCount) { + $total += $refCount['count']; + } + + $doDelete = ($total == 0); + break; + default: + throw new \Exception('Unrecognized cleanup policy: ' . $policy); + } if ($doDelete) { $params = array( diff --git a/Civi/Core/Container.php b/Civi/Core/Container.php index 504f206666..f70369ad15 100644 --- a/Civi/Core/Container.php +++ b/Civi/Core/Container.php @@ -27,10 +27,11 @@ class Container { private static $singleton; /** + * @param bool $reset whether to forcibly rebuild the entire container * @return \Symfony\Component\DependencyInjection\TaggedContainerInterface */ - public static function singleton() { - if (self::$singleton === NULL) { + public static function singleton($reset = FALSE) { + if ($reset || self::$singleton === NULL) { $c = new self(); self::$singleton = $c->createContainer(); } diff --git a/api/v3/Generic.php b/api/v3/Generic.php index f2cb0ea738..75db68b602 100644 --- a/api/v3/Generic.php +++ b/api/v3/Generic.php @@ -113,7 +113,12 @@ function civicrm_api3_generic_getfields($apiRequest) { $hypApiRequest = array('entity' => $apiRequest['entity'], 'action' => $action, 'version' => $apiRequest['version']); try { list ($apiProvider, $hypApiRequest) = \Civi\Core\Container::singleton()->get('civi_api_kernel')->resolve($hypApiRequest); - $helper = '_' . $hypApiRequest['function'] . '_spec'; + if (isset($hypApiRequest['function'])) { + $helper = '_' . $hypApiRequest['function'] . '_spec'; + } else { + // not implemented MagicFunctionProvider + $helper = NULL; + } } catch (\Civi\API\Exception\NotImplementedException $e) { $helper = NULL; } diff --git a/tests/phpunit/CRM/Core/ManagedEntitiesTest.php b/tests/phpunit/CRM/Core/ManagedEntitiesTest.php index 749e71baa6..1764cc80ff 100644 --- a/tests/phpunit/CRM/Core/ManagedEntitiesTest.php +++ b/tests/phpunit/CRM/Core/ManagedEntitiesTest.php @@ -6,6 +6,16 @@ require_once 'CiviTest/CiviUnitTestCase.php'; * Class CRM_Core_ManagedEntitiesTest */ class CRM_Core_ManagedEntitiesTest extends CiviUnitTestCase { + /** + * @var \Civi\API\Kernel + */ + protected $apiKernel; + + /** + * @var \Civi\API\Provider\AdhocProvider + */ + protected $adhocProvider; + /** * @var array(string $shortName => CRM_Core_Module $module) */ @@ -50,12 +60,17 @@ class CRM_Core_ManagedEntitiesTest extends CiviUnitTestCase { 'is_reserved' => 1, ), ); + + $this->apiKernel = \Civi\Core\Container::singleton()->get('civi_api_kernel'); + $this->adhocProvider = new \Civi\API\Provider\AdhocProvider(3, 'CustomSearch'); + $this->apiKernel->registerApiProvider($this->adhocProvider); } function tearDown() { parent::tearDown(); CRM_Core_DAO::singleValueQuery('DELETE FROM civicrm_managed'); CRM_Core_DAO::singleValueQuery('DELETE FROM civicrm_option_value WHERE name like "CRM_Example_%"'); + \Civi\Core\Container::singleton(TRUE); } /** @@ -191,6 +206,60 @@ class CRM_Core_ManagedEntitiesTest extends CiviUnitTestCase { $this->assertEquals($foo['id'], $foo2['id']); } + /** + * Set up an active module with one managed-entity using the + * policy "cleanup=>never". When the managed-entity goes away, + * ensure that the policy is followed (ie the entity is not + * deleted). + */ + function testRemoveDeclaration_CleanupUnused() { + $decls = array(); + + // create first managed entity ('foo') + $decls[] = array_merge($this->fixtures['com.example.one-foo'], array( + 'cleanup' => 'unused' + )); + $me = new CRM_Core_ManagedEntities($this->modules, $decls); + $me->reconcile(); + $foo = $me->get('com.example.one', 'foo'); + $this->assertEquals('CRM_Example_One_Foo', $foo['name']); + $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); + + // Override 'getrefcount' ==> The refcount is 1 + $this->adhocProvider->addAction('getrefcount', 'access CiviCRM', function($apiRequest) { + return civicrm_api3_create_success(array( + array( + 'name' => 'mock', + 'type' => 'mock', + 'count' => 1, + ) + )); + }); + + // Later on, entity definition disappears; but we decide not to do any cleanup (per policy) + $decls = array(); + $me = new CRM_Core_ManagedEntities($this->modules, $decls); + $me->reconcile(); + $foo2 = $me->get('com.example.one', 'foo'); + $this->assertEquals('CRM_Example_One_Foo', $foo2['name']); + $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); + $this->assertEquals($foo['id'], $foo2['id']); + + + // Override 'getrefcount' ==> The refcount is 0 + $this->adhocProvider->addAction('getrefcount', 'access CiviCRM', function($apiRequest) { + return civicrm_api3_create_success(array()); + }); + + // The entity definition disappeared and there's no reference; we decide to cleanup (per policy) + $decls = array(); + $me = new CRM_Core_ManagedEntities($this->modules, $decls); + $me->reconcile(); + $foo3 = $me->get('com.example.one', 'foo'); + $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value WHERE name = "CRM_Example_One_Foo"'); + $this->assertTrue($foo3 === NULL); + } + /** * Setup an active module with a malformed entity declaration */ -- 2.25.1