From 8b165e2f9f403352f1a76a9353b52e470fc8a7c0 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 17 Oct 2022 10:04:44 -0400 Subject: [PATCH] SearchKit - Allow searching for records in "current_domain" Exposes "current_domain" as a choice in SearchKit, and improves API support for handling it when using pseudoconstant syntax. --- Civi/Api4/Service/Spec/SpecFormatter.php | 9 +++++++ Civi/Api4/Utils/FormattingUtil.php | 30 +++++++++++++++++----- tests/phpunit/api/v4/Entity/DomainTest.php | 30 ++++++++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/Civi/Api4/Service/Spec/SpecFormatter.php b/Civi/Api4/Service/Spec/SpecFormatter.php index 0697a64b3e..7357960574 100644 --- a/Civi/Api4/Service/Spec/SpecFormatter.php +++ b/Civi/Api4/Service/Spec/SpecFormatter.php @@ -172,6 +172,15 @@ class SpecFormatter { self::addOptionProps($options, $spec, $bao, $fieldName, $values, $returnFormat); } } + // Special 'current_domain' option + if ($spec->getFkEntity() === 'Domain') { + array_unshift($options, [ + 'id' => 'current_domain', + 'name' => 'current_domain', + 'label' => ts('Current Domain'), + 'icon' => 'fa-sign-in', + ]); + } return $options; } diff --git a/Civi/Api4/Utils/FormattingUtil.php b/Civi/Api4/Utils/FormattingUtil.php index 788a5b73b7..8216a4c328 100644 --- a/Civi/Api4/Utils/FormattingUtil.php +++ b/Civi/Api4/Utils/FormattingUtil.php @@ -89,7 +89,29 @@ class FormattingUtil { */ public static function formatInputValue(&$value, ?string $fieldName, array $fieldSpec, array $params = [], &$operator = NULL, $index = NULL) { // Evaluate pseudoconstant suffix - $suffix = strpos(($fieldName ?? ''), ':'); + $suffix = str_replace(':', '', strstr(($fieldName ?? ''), ':')); + $fk = $fieldSpec['name'] == 'id' ? $fieldSpec['entity'] : $fieldSpec['fk_entity'] ?? NULL; + + // Handle special 'current_domain' option. See SpecFormatter::getOptions + $currentDomain = ($fk === 'Domain' && in_array('current_domain', (array) $value, TRUE)); + if ($currentDomain) { + // If the fieldName uses a suffix, convert + $domainKey = $suffix ?: 'id'; + $domainValue = \CRM_Core_BAO_Domain::getDomain()->$domainKey; + // If the value is an array, only convert the current_domain item + if (is_array($value)) { + foreach ($value as $idx => $val) { + if ($val === 'current_domain') { + $value[$idx] = $domainValue; + } + } + } + else { + $value = $domainValue; + } + } + + // Convert option list suffix to value if ($suffix) { $options = self::getPseudoconstantList($fieldSpec, $fieldName, $params, $operator ? 'get' : 'create'); $value = self::replacePseudoconstant($options, $value, TRUE); @@ -102,12 +124,8 @@ class FormattingUtil { } return; } - $fk = $fieldSpec['name'] == 'id' ? $fieldSpec['entity'] : $fieldSpec['fk_entity'] ?? NULL; - - if ($fk === 'Domain' && $value === 'current_domain') { - $value = \CRM_Core_Config::domainID(); - } + // Special handling for 'current_user' and user lookups if ($fk === 'Contact' && !is_numeric($value)) { $value = \_civicrm_api3_resolve_contactID($value); if ('unknown-user' === $value) { diff --git a/tests/phpunit/api/v4/Entity/DomainTest.php b/tests/phpunit/api/v4/Entity/DomainTest.php index 09acf2d066..951209184e 100644 --- a/tests/phpunit/api/v4/Entity/DomainTest.php +++ b/tests/phpunit/api/v4/Entity/DomainTest.php @@ -20,6 +20,7 @@ namespace api\v4\Entity; use api\v4\Api4TestBase; use Civi\Api4\Domain; +use Civi\Api4\WordReplacement; use Civi\Test\TransactionalInterface; /** @@ -32,6 +33,10 @@ class DomainTest extends Api4TestBase implements TransactionalInterface { ->addValue('name', 'Not current') ->addValue('version', \CRM_Utils_System::version()) ->execute(); + Domain::create(FALSE) + ->addValue('name', 'Also not current') + ->addValue('version', \CRM_Utils_System::version()) + ->execute(); Domain::update(FALSE) ->addValue('name', 'Currently the current domain') @@ -50,6 +55,31 @@ class DomainTest extends Api4TestBase implements TransactionalInterface { $this->assertTrue($getAll['Currently the current domain']['is_active']); $this->assertFalse($getAll['Not current']['is_active']); + $this->assertFalse($getAll['Also not current']['is_active']); + + $getNotCurrent = Domain::get(FALSE) + ->addWhere('id', '!=', 'current_domain') + ->execute()->column('name'); + + $this->assertContains('Not current', $getNotCurrent); + $this->assertContains('Also not current', $getNotCurrent); + $this->assertNotContains('Currently the current domain', $getNotCurrent); + + $wordReplacements = $this->saveTestRecords('WordReplacement', [ + 'records' => [ + ['find_word' => 'One', 'replace_word' => 'First'], + ['find_word' => 'Two', 'replace_word' => 'Second', 'domain_id:name' => 'Not current'], + ['find_word' => 'Three', 'replace_word' => 'Third', 'domain_id:name' => 'Also not current'], + ], + ])->column('id'); + + $fromTwoDomains = WordReplacement::get(FALSE) + ->addWhere('domain_id:name', 'IN', ['current_domain', 'Not current']) + ->execute()->column('id'); + + $this->assertContains($wordReplacements[0], $fromTwoDomains); + $this->assertContains($wordReplacements[1], $fromTwoDomains); + $this->assertNotContains($wordReplacements[2], $fromTwoDomains); } } -- 2.25.1