From 25af38fba7e59e68b6cf827cf7ff86319c9d1ff9 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Tue, 30 Nov 2021 14:53:04 -0500 Subject: [PATCH] APIv4 - Add fixes & tests for domain-specific managed entities --- Civi/Api4/Dashboard.php | 1 + Civi/Api4/Generic/Traits/DAOActionTrait.php | 28 +++++++++++++++++-- .../api/v4/Entity/ManagedEntityTest.php | 22 +++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Civi/Api4/Dashboard.php b/Civi/Api4/Dashboard.php index de640785254d..882b9a3a75e6 100644 --- a/Civi/Api4/Dashboard.php +++ b/Civi/Api4/Dashboard.php @@ -25,5 +25,6 @@ * @package Civi\Api4 */ class Dashboard extends Generic\DAOEntity { + use Generic\Traits\ManagedEntity; } diff --git a/Civi/Api4/Generic/Traits/DAOActionTrait.php b/Civi/Api4/Generic/Traits/DAOActionTrait.php index 59a62fce039f..01b7856052d4 100644 --- a/Civi/Api4/Generic/Traits/DAOActionTrait.php +++ b/Civi/Api4/Generic/Traits/DAOActionTrait.php @@ -198,8 +198,12 @@ protected function formatWriteValues(&$record) { * @param array $record */ private function resolveFKValues(array &$record): void { + // Resolve domain id first + uksort($record, function($a, $b) { + return substr($a, 0, 9) == 'domain_id' ? -1 : 1; + }); foreach ($record as $key => $value) { - if (substr_count($key, '.') !== 1) { + if (!$value || substr_count($key, '.') !== 1) { continue; } [$fieldName, $fkField] = explode('.', $key); @@ -208,7 +212,27 @@ private function resolveFKValues(array &$record): void { continue; } $fkDao = CoreUtil::getBAOFromApiName($field['fk_entity']); - $record[$fieldName] = \CRM_Core_DAO::getFieldValue($fkDao, $value, 'id', $fkField); + // Constrain search to the domain of the current entity + $domainConstraint = NULL; + if (isset($fkDao::getSupportedFields()['domain_id'])) { + if (!empty($record['domain_id'])) { + $domainConstraint = $record['domain_id'] === 'current_domain' ? \CRM_Core_Config::domainID() : $record['domain_id']; + } + elseif (!empty($record['id']) && isset($this->entityFields()['domain_id'])) { + $domainConstraint = \CRM_Core_DAO::getFieldValue($this->getBaoName(), $record['id'], 'domain_id'); + } + } + if ($domainConstraint) { + $fkSearch = new $fkDao(); + $fkSearch->domain_id = $domainConstraint; + $fkSearch->$fkField = $value; + $fkSearch->find(TRUE); + $record[$fieldName] = $fkSearch->id; + } + // Simple lookup without all the fuss about domains + else { + $record[$fieldName] = \CRM_Core_DAO::getFieldValue($fkDao, $value, 'id', $fkField); + } unset($record[$key]); } } diff --git a/tests/phpunit/api/v4/Entity/ManagedEntityTest.php b/tests/phpunit/api/v4/Entity/ManagedEntityTest.php index 844c578e97bf..79f21e2d878e 100644 --- a/tests/phpunit/api/v4/Entity/ManagedEntityTest.php +++ b/tests/phpunit/api/v4/Entity/ManagedEntityTest.php @@ -19,6 +19,7 @@ namespace api\v4\Entity; use api\v4\UnitTestCase; +use Civi\Api4\Domain; use Civi\Api4\Navigation; use Civi\Api4\OptionGroup; use Civi\Api4\OptionValue; @@ -460,6 +461,18 @@ public function testManagedNavigationWeights() { ], ]; + // Throw a monkey wrench by placing duplicates in another domain + $d2 = Domain::create(FALSE) + ->addValue('name', 'Decoy domain') + ->addValue('version', \CRM_Utils_System::version()) + ->execute()->single(); + foreach ($this->_managedEntities as $item) { + $decoys[] = civicrm_api4('Navigation', 'create', [ + 'checkPermissions' => FALSE, + 'values' => ['domain_id' => $d2['id']] + $item['params']['values'], + ])->first(); + } + // Refresh managed entities with module active $allModules = [ new \CRM_Core_Module('unit.test.fake.ext', TRUE), @@ -491,6 +504,15 @@ public function testManagedNavigationWeights() { $this->assertEquals(TRUE, $children[$index]['is_active']); } + // Try exporting the decoy records + $decoyExport = Navigation::export(FALSE) + ->setId($decoys[0]['id']) + ->execute(); + $this->assertCount(4, $decoyExport); + $this->assertEquals('Decoy domain', $decoyExport[0]['params']['values']['domain_id.name']); + $this->assertEquals('Decoy domain', $decoyExport[1]['params']['values']['domain_id.name']); + $this->assertArrayNotHasKey('weight', $decoyExport[1]['params']['values']); + // Refresh managed entities with module disabled $allModules = [ new \CRM_Core_Module('unit.test.fake.ext', FALSE),