SearchKit - Allow random sorting
authorColeman Watts <coleman@civicrm.org>
Wed, 18 Aug 2021 20:26:53 +0000 (16:26 -0400)
committerColeman Watts <coleman@civicrm.org>
Wed, 18 Aug 2021 23:35:34 +0000 (19:35 -0400)
Civi/Api4/Query/SqlFunctionRAND.php [new file with mode: 0644]
ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js
ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplaySort.html
tests/phpunit/api/v4/Action/SqlFunctionTest.php

diff --git a/Civi/Api4/Query/SqlFunctionRAND.php b/Civi/Api4/Query/SqlFunctionRAND.php
new file mode 100644 (file)
index 0000000..1cb0cfe
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Api4\Query;
+
+/**
+ * Sql function
+ */
+class SqlFunctionRAND extends SqlFunction {
+
+  protected static $category = self::CATEGORY_MATH;
+
+  protected static function params(): array {
+    return [];
+  }
+
+  /**
+   * @return string
+   */
+  public static function getTitle(): string {
+    return ts('Random Number');
+  }
+
+}
index 7ea85b38884adb5dee48af95ce3424f5fb85c8c1..a5694f4c421f8dbb2fdd526a8a4a0584101cf16c 100644 (file)
           return _.findIndex(ctrl.display.settings.sort, [key]) >= 0;
         }
         return {
-          results: [{
-            text: ts('Columns'),
-            children: ctrl.crmSearchAdmin.getSelectFields(disabledIf)
-          }].concat(ctrl.crmSearchAdmin.getAllFields('', ['Field', 'Custom'], disabledIf))
+          results: [
+            {
+              text: ts('Random'),
+              icon: 'crm-i fa-random',
+              id: 'RAND()',
+              disabled: disabledIf('RAND()')
+            },
+            {
+              text: ts('Columns'),
+              children: ctrl.crmSearchAdmin.getSelectFields(disabledIf)
+            }
+          ].concat(ctrl.crmSearchAdmin.getAllFields('', ['Field', 'Custom'], disabledIf))
         };
       };
 
index 4e548899aa977b2aabb8b4a21aa5efb23cdaf3b1..a3a1cf737e2330c39eec10a222918a03a877ced8 100644 (file)
@@ -1,7 +1,7 @@
 <div class="form-inline" ng-repeat="sort in $ctrl.display.settings.sort">
   <label for="crm-search-display-sort-{{$index}}">{{ $index ? ts('Also by') : ts('Sort by') }}</label>
   <input id="crm-search-display-sort-{{$index}}" class="form-control huge" ng-model="sort[0]" crm-ui-select="{data: $ctrl.parent.fieldsForSort}" />
-  <select class="form-control" ng-model="sort[1]">
+  <select class="form-control" ng-model="sort[1]" ng-show="sort[0] !== 'RAND()'">
     <option value="ASC">{{ ts('Ascending') }}</option>
     <option value="DESC">{{ ts('Descending') }}</option>
   </select>
index 078b9eeaa82af562847b5659a48312a3e052c743..5cf7373770d89da00fb1ae6544bd90ecdf3186a5 100644 (file)
@@ -199,4 +199,21 @@ class SqlFunctionTest extends UnitTestCase {
     }
   }
 
+  public function testRandFunction() {
+    $cid = Contact::create(FALSE)
+      ->addValue('first_name', 'hello')
+      ->execute()->first()['id'];
+
+    $result = Contact::get(FALSE)
+      ->addSelect('RAND() AS rand')
+      ->addOrderBy('RAND()')
+      ->setDebug(TRUE)
+      ->setLimit(1)
+      ->execute();
+
+    $this->assertStringContainsString('ORDER BY RAND()', $result->debug['sql'][0]);
+    $this->assertGreaterThanOrEqual(0, $result[0]['rand']);
+    $this->assertLessThan(1, $result[0]['rand']);
+  }
+
 }