From 7e8b793a553b3b0c752ae83c0c7416c2460e8e72 Mon Sep 17 00:00:00 2001 From: colemanw Date: Fri, 1 Sep 2023 23:27:23 -0400 Subject: [PATCH] Add API-based EntityLookupTrait --- Civi/API/EntityLookupTrait.php | 89 +++++++++++++++++++++ Civi/Test/EntityTrait.php | 6 +- tests/phpunit/Civi/API/EntityLookupTest.php | 20 +++++ 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 Civi/API/EntityLookupTrait.php create mode 100644 tests/phpunit/Civi/API/EntityLookupTest.php diff --git a/Civi/API/EntityLookupTrait.php b/Civi/API/EntityLookupTrait.php new file mode 100644 index 0000000000..d205dee8fd --- /dev/null +++ b/Civi/API/EntityLookupTrait.php @@ -0,0 +1,89 @@ +lookup()` + * + * @param string $apiEntityName + * @param string $nickname + * Handle to use to retrieve values with `$this->lookup()` + * @param array $identifier + * A unique key or combination of keys to uniquely identify the record (usually id) + * Most commonly looks like `['id' => 123]` + */ + protected function define(string $apiEntityName, string $nickname, array $identifier): void { + $this->entityLookupDefinitions[$nickname] = [ + 'entityName' => $apiEntityName, + 'identifier' => $identifier, + ]; + $this->entityLookupValues[$nickname] = []; + } + + /** + * Retrieve a field value for a defined entity + * + * @param string $nickname + * Handle set by `$this->define()` + * @param string $fieldName + * @return mixed + * @throws \CRM_Core_Exception + */ + public function lookup(string $nickname, string $fieldName) { + if (!isset($this->entityLookupValues[$nickname])) { + throw new \CRM_Core_Exception(sprintf('Cannot lookup entity "%s" before it has been defined.', $nickname)); + } + if (array_key_exists($fieldName, $this->entityLookupValues[$nickname])) { + return $this->entityLookupValues[$nickname][$fieldName]; + } + $entityName = $this->entityLookupDefinitions[$nickname]['entityName']; + $params = [ + 'select' => [$fieldName], + 'where' => [], + 'checkPermissions' => FALSE, + ]; + foreach ($this->entityLookupDefinitions[$nickname]['identifier'] as $key => $val) { + $params['where'][] = [$key, '=', $val]; + } + if (!$this->entityLookupValues[$nickname]) { + $params['select'][] = '*'; + if ($entityName === 'Contact') { + $params['select'][] = 'email_primary.*'; + } + } + // If requesting a join or a custom field, fetch them all by replacing the last part with a * + if (str_contains($fieldName, '.')) { + $parts = explode('.', $fieldName); + $parts[count($parts) - 1] = '*'; + $params['select'][] = implode('.', $parts); + } + $retrieved = civicrm_api4($entityName, 'get', $params)->single(); + $this->entityLookupValues[$nickname] += $retrieved; + return $this->entityLookupValues[$nickname][$fieldName] ?? NULL; + } + +} diff --git a/Civi/Test/EntityTrait.php b/Civi/Test/EntityTrait.php index 1dfe24cbfa..6a3f0707b9 100644 --- a/Civi/Test/EntityTrait.php +++ b/Civi/Test/EntityTrait.php @@ -47,15 +47,15 @@ trait EntityTrait { * Create an entity, recording it's details for tearDown. * * @param string $entity - * @param array $params + * @param array $values * @param string $identifier * * @return array */ - protected function createTestEntity(string $entity, array $params, string $identifier = 'default'): array { + protected function createTestEntity(string $entity, array $values, string $identifier = 'default'): array { $result = NULL; try { - $result = \civicrm_api4($entity, 'create', ['values' => $params, 'checkPermissions' => FALSE])->first(); + $result = \civicrm_api4($entity, 'create', ['values' => $values, 'checkPermissions' => FALSE])->single(); $this->setTestEntityID($entity, $result['id'], $identifier); } catch (\CRM_Core_Exception $e) { diff --git a/tests/phpunit/Civi/API/EntityLookupTest.php b/tests/phpunit/Civi/API/EntityLookupTest.php new file mode 100644 index 0000000000..954c4face8 --- /dev/null +++ b/tests/phpunit/Civi/API/EntityLookupTest.php @@ -0,0 +1,20 @@ +createTestEntity('Contact', ['first_name' => 'Bob', 'last_name' => 'One', 'gender_id:name' => 'Male', 'email_primary.email' => 'bob@one.test']); + $jan = $this->createTestEntity('Contact', ['first_name' => 'Jan', 'last_name' => 'Two', 'gender_id:name' => 'Female', 'external_identifier' => uniqid()]); + $this->define('Contact', 'Bob', ['id' => $bob['id']]); + $this->define('Contact', 'Jan', ['external_identifier' => $jan['external_identifier']]); + $this->assertEquals('One', $this->lookup('Bob', 'last_name')); + $this->assertEquals('bob@one.test', $this->lookup('Bob', 'email_primary.email')); + $this->assertEquals('Male', $this->lookup('Bob', 'gender_id:name')); + $this->assertEquals('Two', $this->lookup('Jan', 'last_name')); + $this->assertEquals('Female', $this->lookup('Jan', 'gender_id:name')); + } + +} -- 2.25.1