X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FCore%2FManagedEntities.php;h=10a7ff36f2080707a6fb2dc455d43e62f469258f;hb=7e5524d42ce21bb4cd64cec30ad63b68d882c108;hp=c06e06066a555096ac01187034a1426e3801f83f;hpb=0dd545869c9046003e81e4a18e1ece1bd15f868d;p=civicrm-core.git diff --git a/CRM/Core/ManagedEntities.php b/CRM/Core/ManagedEntities.php index c06e06066a..10a7ff36f2 100644 --- a/CRM/Core/ManagedEntities.php +++ b/CRM/Core/ManagedEntities.php @@ -6,15 +6,24 @@ * deactivated, and deleted in tandem with their modules. */ class CRM_Core_ManagedEntities { + + public static function getCleanupOptions() { + return array( + 'always' => ts('Always'), + 'never' => ts('Never'), + 'unused' => ts('If Unused'), + ); + } + /** * @var array($status => array($name => CRM_Core_Module)) */ - public $moduleIndex; + protected $moduleIndex; /** * @var array per hook_civicrm_managed */ - public $declarations; + protected $declarations; /** * Get an instance @@ -22,28 +31,43 @@ class CRM_Core_ManagedEntities { public static function singleton($fresh = FALSE) { static $singleton; if ($fresh || !$singleton) { - $declarations = array(); - foreach (CRM_Core_Component::getEnabledComponents() as $component) { - /** @var CRM_Core_Component_Info $component */ - $declarations = array_merge($declarations, $component->getManagedEntities()); - } - CRM_Utils_Hook::managed($declarations); - $singleton = new CRM_Core_ManagedEntities(CRM_Core_Module::getAll(), $declarations); + $singleton = new CRM_Core_ManagedEntities(CRM_Core_Module::getAll(), NULL); } return $singleton; } + /** + * Perform an asynchronous reconciliation when the transaction ends. + */ + public static function scheduleReconcilation() { + CRM_Core_Transaction::addCallback( + CRM_Core_Transaction::PHASE_POST_COMMIT, + function () { + CRM_Core_ManagedEntities::singleton(TRUE)->reconcile(); + }, + array(), + 'ManagedEntities::reconcile' + ); + } + /** * @param array $modules CRM_Core_Module * @param array $declarations per hook_civicrm_managed */ public function __construct($modules, $declarations) { $this->moduleIndex = self::createModuleIndex($modules); - $this->declarations = self::cleanDeclarations($declarations); + + if ($declarations !== NULL) { + $this->declarations = self::cleanDeclarations($declarations); + } else { + $this->declarations = NULL; + } } /** * 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(); @@ -58,7 +82,7 @@ class CRM_Core_ManagedEntities { $result = civicrm_api3($dao->entity_type, 'getsingle', $params); } catch (Exception $e) { - $this->onApiError($params, $result); + $this->onApiError($dao->entity_type, 'getsingle', $params, $result); } return $result; } else { @@ -67,7 +91,7 @@ class CRM_Core_ManagedEntities { } public function reconcile() { - if ($error = $this->validate($this->declarations)) { + if ($error = $this->validate($this->getDeclarations())) { throw new Exception($error); } $this->reconcileEnabledModules(); @@ -81,7 +105,7 @@ class CRM_Core_ManagedEntities { // an active module -- because we got it from a hook! // index by moduleName,name - $decls = self::createDeclarationIndex($this->moduleIndex, $this->declarations); + $decls = self::createDeclarationIndex($this->moduleIndex, $this->getDeclarations()); foreach ($decls as $moduleName => $todos) { if (isset($this->moduleIndex[TRUE][$moduleName])) { $this->reconcileEnabledModule($this->moduleIndex[TRUE][$moduleName], $todos); @@ -164,7 +188,7 @@ class CRM_Core_ManagedEntities { public function insertNewEntity($todo) { $result = civicrm_api($todo['entity'], 'create', $todo['params']); if ($result['is_error']) { - $this->onApiError($todo['params'], $result); + $this->onApiError($todo['entity'], 'create', $todo['params'], $result); } $dao = new CRM_Core_DAO_Managed(); @@ -172,6 +196,7 @@ class CRM_Core_ManagedEntities { $dao->name = $todo['name']; $dao->entity_type = $todo['entity']; $dao->entity_id = $result['id']; + $dao->cleanup = CRM_Utils_Array::value('cleanup', $todo); $dao->save(); } @@ -193,9 +218,14 @@ class CRM_Core_ManagedEntities { $params = array_merge($defaults, $todo['params']); $result = civicrm_api($dao->entity_type, 'create', $params); if ($result['is_error']) { - $this->onApiError($params, $result); + $this->onApiError($dao->entity_type, 'create',$params, $result); } } + + if (isset($todo['cleanup'])) { + $dao->cleanup = $todo['cleanup']; + $dao->update(); + } } /** @@ -215,7 +245,7 @@ class CRM_Core_ManagedEntities { ); $result = civicrm_api($dao->entity_type, 'create', $params); if ($result['is_error']) { - $this->onApiError($params, $result); + $this->onApiError($dao->entity_type, 'create',$params, $result); } } } @@ -226,18 +256,58 @@ class CRM_Core_ManagedEntities { * @param CRM_Core_DAO_Managed $dao */ public function removeStaleEntity($dao) { - $params = array( - 'version' => 3, - 'id' => $dao->entity_id, - ); - $result = civicrm_api($dao->entity_type, 'delete', $params); - if ($result['is_error']) { - $this->onApiError($params, $result); + $policy = empty($dao->cleanup) ? 'always' : $dao->cleanup; + 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); } - CRM_Core_DAO::executeQuery('DELETE FROM civicrm_managed WHERE id = %1', array( - 1 => array($dao->id, 'Integer') - )); + if ($doDelete) { + $params = array( + 'version' => 3, + 'id' => $dao->entity_id, + ); + $result = civicrm_api($dao->entity_type, 'delete', $params); + if ($result['is_error']) { + $this->onApiError($dao->entity_type, 'delete', $params, $result); + } + + CRM_Core_DAO::executeQuery('DELETE FROM civicrm_managed WHERE id = %1', array( + 1 => array($dao->id, 'Integer') + )); + } + } + + public function getDeclarations() { + if ($this->declarations === NULL) { + $this->declarations = array(); + foreach (CRM_Core_Component::getEnabledComponents() as $component) { + /** @var CRM_Core_Component_Info $component */ + $this->declarations = array_merge($this->declarations, $component->getManagedEntities()); + } + CRM_Utils_Hook::managed($this->declarations); + $this->declarations = self::cleanDeclarations($this->declarations); + } + return $this->declarations; } /** @@ -309,13 +379,17 @@ class CRM_Core_ManagedEntities { } /** - * @param $params - * @param $result + * @param string $entity + * @param string $action + * @param array $params + * @param array $result * * @throws Exception */ - protected function onApiError($params, $result) { + protected function onApiError($entity, $action, $params, $result) { CRM_Core_Error::debug_var('ManagedEntities_failed', array( + 'entity' => $entity, + 'action' => $action, 'params' => $params, 'result' => $result, ));