diff --git a/CRM/Core/ManagedEntities.php b/CRM/Core/ManagedEntities.php index eeb78f947d60..ff9ae5268ef1 100644 --- a/CRM/Core/ManagedEntities.php +++ b/CRM/Core/ManagedEntities.php @@ -311,22 +311,30 @@ protected function reconcileUnknownModules() { * Entity specification (per hook_civicrm_managedEntities). */ protected function insertNewEntity($todo) { - if ($todo['params']['version'] == 4) { - $todo['params']['checkPermissions'] = FALSE; - } - - $result = civicrm_api($todo['entity_type'], 'create', ['debug' => TRUE] + $todo['params']); - if (!empty($result['is_error'])) { - $this->onApiError($todo['entity_type'], 'create', $todo['params'], $result); + $params = $todo['params']; + // APIv4 + if ($params['version'] == 4) { + $params['checkPermissions'] = FALSE; + // Use "save" instead of "create" action to accommodate a "match" param + $params['records'] = [$params['values']]; + unset($params['values']); + $result = civicrm_api4($todo['entity_type'], 'save', $params); + $id = $result->first()['id']; + } + // APIv3 + else { + $result = civicrm_api($todo['entity_type'], 'create', $params); + if (!empty($result['is_error'])) { + $this->onApiError($todo['entity_type'], 'create', $params, $result); + } + $id = $result['id']; } $dao = new CRM_Core_DAO_Managed(); $dao->module = $todo['module']; $dao->name = $todo['name']; $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']; + $dao->entity_id = $id; $dao->cleanup = $todo['cleanup'] ?? NULL; $dao->save(); } @@ -382,6 +390,8 @@ protected function updateExistingEntity($dao, $todo) { elseif ($doUpdate && $todo['params']['version'] == 4) { $params = ['checkPermissions' => FALSE] + $todo['params']; $params['values']['id'] = $dao->entity_id; + // 'match' param doesn't apply to "update" action + unset($params['match']); civicrm_api4($dao->entity_type, 'update', $params); } diff --git a/tests/phpunit/api/v4/Entity/ManagedEntityTest.php b/tests/phpunit/api/v4/Entity/ManagedEntityTest.php index 481beb99af09..13eb440498a0 100644 --- a/tests/phpunit/api/v4/Entity/ManagedEntityTest.php +++ b/tests/phpunit/api/v4/Entity/ManagedEntityTest.php @@ -586,6 +586,57 @@ public function testExportAndCreateGroup() { $this->assertGreaterThan($original['id'], $created['id']); } + /** + * Tests a scenario where a record may already exist and we want to make it a managed entity + */ + public function testMatchExisting() { + $optionGroup = OptionGroup::create(FALSE) + ->addValue('title', 'My pre-existing group') + ->addValue('name', 'My_pre_existing_group') + ->execute()->first(); + + $managed = [ + 'module' => 'civicrm', + 'name' => 'preExistingGroup', + 'entity' => 'OptionGroup', + 'cleanup' => 'always', + 'update' => 'always', + 'params' => [ + 'version' => 4, + 'values' => [ + 'name' => $optionGroup['name'], + 'title' => "Cool new title", + 'description' => 'Cool new description', + ], + ], + ]; + $this->_managedEntities = [$managed]; + + // Without "match" in the params, it will try and fail to add a duplicate managed record + try { + \CRM_Core_ManagedEntities::singleton(TRUE)->reconcile(); + } + catch (\Exception $e) { + } + $this->assertStringContainsString('already exists', $e->getMessage()); + + // Now reconcile using a match param + $managed['params']['match'] = ['name']; + $this->_managedEntities = [$managed]; + \CRM_Core_ManagedEntities::singleton(TRUE)->reconcile(); + + $managedGroup = OptionGroup::get(FALSE) + ->addWhere('name', '=', $optionGroup['name']) + ->addSelect('id', 'title', 'description', 'base_module') + ->execute()->single(); + + $this->assertEquals($optionGroup['id'], $managedGroup['id']); + $this->assertEquals('Cool new title', $managedGroup['title']); + $this->assertEquals('Cool new description', $managedGroup['description']); + // The existing record has been converted to a managed entity! + $this->assertEquals('civicrm', $managedGroup['base_module']); + } + /** * @dataProvider sampleEntityTypes * @param string $entityName