SearchKit - Allow searching for records in "current_domain"
authorColeman Watts <coleman@civicrm.org>
Mon, 17 Oct 2022 14:04:44 +0000 (10:04 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 17 Oct 2022 14:10:44 +0000 (10:10 -0400)
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
Civi/Api4/Utils/FormattingUtil.php
tests/phpunit/api/v4/Entity/DomainTest.php

index 0697a64b3eca8d649fd2ec26b6a7eb44e4deaa36..73579605747a7e6ed8ec9207990067c26fae28f3 100644 (file)
@@ -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;
   }
 
index 788a5b73b78a768bfe74a2d995f7bd62396cc7ec..8216a4c328ac39f9ca756c95094935943a814913 100644 (file)
@@ -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) {
index 09acf2d066fb7c3729814a3efe99473f7fcd6085..951209184e41d179dfd9ef92e32c6a20ab9044ca 100644 (file)
@@ -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);
   }
 
 }