From fe59b2a7566ab760582b1b29ab7f3734f6020d0d Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Wed, 15 Feb 2017 22:32:36 -0500 Subject: [PATCH] CRM-20034 - Support OR grouping of api get params --- Civi/API/Api3SelectQuery.php | 41 ++++++++++++++++++--------- tests/phpunit/api/v3/ActivityTest.php | 29 +++++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/Civi/API/Api3SelectQuery.php b/Civi/API/Api3SelectQuery.php index 984b174668..77bdd1b4b7 100644 --- a/Civi/API/Api3SelectQuery.php +++ b/Civi/API/Api3SelectQuery.php @@ -36,6 +36,7 @@ class Api3SelectQuery extends SelectQuery { * @inheritDoc */ protected function buildWhereClause() { + $filters = array(); foreach ($this->where as $key => $value) { $table_name = NULL; $column_name = NULL; @@ -104,23 +105,37 @@ class Api3SelectQuery extends SelectQuery { // Just ignore this for the $where_clause. continue; } - if (!is_array($value)) { - $this->query->where(array("`$table_name`.`$column_name` = @value"), array( - "@value" => $value, - )); + $operator = is_array($value) ? \CRM_Utils_Array::first(array_keys($value)) : NULL; + if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators())) { + $value = array('=' => $value); } - else { - // We expect only one element in the array, of the form - // "operator" => "rhs". - $operator = \CRM_Utils_Array::first(array_keys($value)); - if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators())) { - $this->query->where(array("{$table_name}.{$column_name} = @value"), array("@value" => $value)); - } - else { - $this->query->where(\CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value)); + $filters[$key] = \CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value); + } + // Support OR groups + if (!empty($this->where['options']['or'])) { + $orGroups = $this->where['options']['or']; + if (is_string($orGroups)) { + $orGroups = array_map('trim', explode(',', $orGroups)); + } + if (!is_array(\CRM_Utils_Array::first($orGroups))) { + $orGroups = array($orGroups); + } + foreach ($orGroups as $orGroup) { + $orClause = array(); + foreach ($orGroup as $key) { + if (!isset($filters[$key])) { + throw new \CiviCRM_API3_Exception("'$key' specified in OR group but not added to params"); + } + $orClause[] = $filters[$key]; + unset($filters[$key]); } + $this->query->where(implode(' OR ', $orClause)); } } + // Add the remaining params using AND + foreach ($filters as $filter) { + $this->query->where($filter); + } } /** diff --git a/tests/phpunit/api/v3/ActivityTest.php b/tests/phpunit/api/v3/ActivityTest.php index afe7e74b88..526e03dfd8 100644 --- a/tests/phpunit/api/v3/ActivityTest.php +++ b/tests/phpunit/api/v3/ActivityTest.php @@ -1289,4 +1289,33 @@ class api_v3_ActivityTest extends CiviUnitTestCase { } } + public function testGetWithOr() { + $acts = array( + 'test or 1' => 'orOperator', + 'test or 2' => 'orOperator', + 'test or 3' => 'nothing', + ); + foreach ($acts as $subject => $details) { + $params = $this->_params; + $params['subject'] = $subject; + $params['details'] = $details; + $this->callAPISuccess('Activity', 'create', $params); + } + $result = $this->callAPISuccess('Activity', 'get', array( + 'details' => 'orOperator', + )); + $this->assertEquals(2, $result['count']); + $result = $this->callAPISuccess('Activity', 'get', array( + 'details' => 'orOperator', + 'subject' => 'test or 3', + )); + $this->assertEquals(0, $result['count']); + $result = $this->callAPISuccess('Activity', 'get', array( + 'details' => 'orOperator', + 'subject' => 'test or 3', + 'options' => array('or' => array(array('details', 'subject'))), + )); + $this->assertEquals(3, $result['count']); + } + } -- 2.25.1