<?php
+use Civi\Api4\Managed;
+
/**
* The ManagedEntities system allows modules to add records to the database
* declaratively. Those records will be automatically inserted, updated,
*/
protected $moduleIndex;
+ /**
+ * Actions arising from the managed entities.
+ *
+ * @var array
+ */
+ protected $managedActions = [];
+
/**
* @var array
* List of all entity declarations.
/**
* Read a managed entity using APIv3.
*
+ * @deprecated
+ *
* @param string $moduleName
* The name of the module which declared entity.
* @param string $name
if (CRM_Core_Config::singleton()->isUpgradeMode() && !$ignoreUpgradeMode) {
return;
}
+
if ($error = $this->validate($this->getDeclarations())) {
throw new CRM_Core_Exception($error);
}
+ $this->loadManagedEntityActions();
$this->reconcileEnabledModules();
$this->reconcileDisabledModules();
$this->reconcileUnknownModules();
$decls = $this->createDeclarationIndex($this->moduleIndex, $this->getDeclarations());
foreach ($decls as $moduleName => $todos) {
if ($this->isModuleEnabled($moduleName)) {
- $this->reconcileEnabledModule($this->moduleIndex[TRUE][$moduleName], $todos);
+ $this->reconcileEnabledModule($moduleName);
}
}
}
* For one enabled module, add new entities, update existing entities,
* and remove orphaned (stale) entities.
*
- * @param \CRM_Core_Module $module
- * @param array $todos
- * List of entities currently declared by this module.
- * array(string $name => array $entityDef).
+ * @param string $module
*/
- public function reconcileEnabledModule(CRM_Core_Module $module, $todos) {
- $dao = new CRM_Core_DAO_Managed();
- $dao->module = $module->name;
- $dao->find();
- while ($dao->fetch()) {
- if (isset($todos[$dao->name]) && $todos[$dao->name]) {
- // update existing entity; remove from $todos
- $this->updateExistingEntity($dao, $todos[$dao->name]);
- unset($todos[$dao->name]);
- }
- else {
- // remove stale entity; not in $todos
- $this->removeStaleEntity($dao);
- }
+ public function reconcileEnabledModule(string $module): void {
+ foreach ($this->getManagedEntitiesToUpdate(['module' => $module]) as $todo) {
+ $dao = new CRM_Core_DAO_Managed();
+ $dao->module = $todo['module'];
+ $dao->name = $todo['name'];
+ $dao->entity_type = $todo['entity_type'];
+ $dao->entity_id = $todo['entity_id'];
+ $dao->id = $todo['id'];
+ $this->updateExistingEntity($dao, $todo);
}
- // create new entities from leftover $todos
- foreach ($todos as $name => $todo) {
+ foreach ($this->getManagedEntitiesToDelete(['module' => $module]) as $todo) {
+ $dao = new CRM_Core_DAO_Managed();
+ $dao->module = $todo['module'];
+ $dao->name = $todo['name'];
+ $dao->entity_type = $todo['entity_type'];
+ $dao->id = $todo['id'];
+ $dao->cleanup = $todo['cleanup'];
+ $dao->entity_id = $todo['entity_id'];
+ $this->removeStaleEntity($dao);
+ }
+ foreach ($this->getManagedEntitiesToCreate(['module' => $module]) as $todo) {
$this->insertNewEntity($todo);
}
}
+ /**
+ * Get the managed entities to be created.
+ *
+ * @param array $filters
+ *
+ * @return array
+ */
+ protected function getManagedEntitiesToCreate(array $filters = []): array {
+ return $this->getManagedEntities(array_merge($filters, ['managed_action' => 'create']));
+ }
+
+ /**
+ * Get the managed entities to be created.
+ *
+ * @param array $filters
+ *
+ * @return array
+ */
+ protected function getManagedEntitiesToUpdate(array $filters = []): array {
+ return $this->getManagedEntities(array_merge($filters, ['managed_action' => 'update']));
+ }
+
+ /**
+ * Get the managed entities to be deleted.
+ *
+ * @param array $filters
+ *
+ * @return array
+ */
+ protected function getManagedEntitiesToDelete(array $filters = []): array {
+ return $this->getManagedEntities(array_merge($filters, ['managed_action' => 'delete']));
+ }
+
+ /**
+ * Get the managed entities that fit the criteria.
+ *
+ * @param array $filters
+ *
+ * @return array
+ */
+ protected function getManagedEntities(array $filters = []): array {
+ $return = [];
+ foreach ($this->managedActions as $actionKey => $action) {
+ foreach ($filters as $filterKey => $filterValue) {
+ if ($action[$filterKey] !== $filterValue) {
+ continue 2;
+ }
+ }
+ $return[$actionKey] = $action;
+ }
+ return $return;
+ }
+
/**
* For all disabled modules, disable any managed entities.
*/
* Entity specification (per hook_civicrm_managedEntities).
*/
protected function insertNewEntity($todo) {
- $result = civicrm_api($todo['entity'], 'create', $todo['params']);
+ $result = civicrm_api($todo['entity_type'], 'create', $todo['params']);
if (!empty($result['is_error'])) {
- $this->onApiError($todo['entity'], 'create', $todo['params'], $result);
+ $this->onApiError($todo['entity_type'], 'create', $todo['params'], $result);
}
$dao = new CRM_Core_DAO_Managed();
$dao->module = $todo['module'];
$dao->name = $todo['name'];
- $dao->entity_type = $todo['entity'];
+ $dao->entity_type = $todo['entity_type'];
// A fatal error will result if there is no valid id but if
// this is v4 api we might need to access it via ->first().
$dao->entity_id = $result['id'] ?? $result->first()['id'];
* Remove a stale entity (if policy allows).
*
* @param CRM_Core_DAO_Managed $dao
- * @throws Exception
+ * @throws CRM_Core_Exception
*/
protected function removeStaleEntity($dao) {
$policy = empty($dao->cleanup) ? 'always' : $dao->cleanup;
break;
default:
- throw new \Exception('Unrecognized cleanup policy: ' . $policy);
+ throw new CRM_Core_Exception('Unrecognized cleanup policy: ' . $policy);
}
if ($doDelete) {
$this->declarations = $this->cleanDeclarations($this->declarations);
}
+ protected function loadManagedEntityActions(): void {
+ $managedEntities = Managed::get(FALSE)->addSelect('*')->execute();
+ foreach ($managedEntities as $managedEntity) {
+ $key = "{$managedEntity['module']}_{$managedEntity['name']}_{$managedEntity['entity_type']}";
+ // Set to 'delete' - it will be overwritten below if it is to be updated.
+ $action = 'delete';
+ $this->managedActions[$key] = array_merge($managedEntity, ['managed_action' => $action]);
+ }
+ foreach ($this->declarations as $declaration) {
+ $key = "{$declaration['module']}_{$declaration['name']}_{$declaration['entity']}";
+ if (isset($this->managedActions[$key])) {
+ $this->managedActions[$key]['params'] = $declaration['params'];
+ $this->managedActions[$key]['managed_action'] = 'update';
+ $this->managedActions[$key]['cleanup'] = $declaration['cleanup'] ?? NULL;
+ $this->managedActions[$key]['update'] = $declaration['update'] ?? 'always';
+ }
+ else {
+ $this->managedActions[$key] = [
+ 'module' => $declaration['module'],
+ 'name' => $declaration['name'],
+ 'entity_type' => $declaration['entity'],
+ 'managed_action' => 'create',
+ 'params' => $declaration['params'],
+ 'cleanup' => $declaration['cleanup'] ?? NULL,
+ 'update' => $declaration['update'] ?? 'always',
+ ];
+ }
+ }
+ }
+
}