CRM-13294 support for api style array of ids as a param for contact_get
authoreileen <eileen@fuzion.co.nz>
Tue, 27 Aug 2013 02:19:29 +0000 (14:19 +1200)
committerTim Otten <totten@civicrm.org>
Tue, 27 Aug 2013 23:51:23 +0000 (16:51 -0700)
CRM/Contact/BAO/Query.php
CRM/Core/DAO.php
api/v3/utils.php
tests/phpunit/api/v3/ContactTest.php

index 303d130dc01fee0854f9a723ee0c8aa8ff4d5f54..d4405f4bacf4daa9750c51de86bf37611bf64f8a 100644 (file)
@@ -1758,6 +1758,13 @@ class CRM_Contact_BAO_Query {
           }
           elseif (is_array($this->_params[$id][2])) {
             $idList = implode("','", $this->_params[$id][2]);
+            //why on earth do they put ' in the middle & not on the outside? We have to assume it's
+            //to support 'something' so lets add them conditionally to support the api (which is a tested flow
+            // so if you are looking to alter this check api test results
+            if(strpos(trim($idList), "'") > 0) {
+              $idList = "'" . $idList . "'";
+            }
+
             $this->_where[0][] = "contact_a.id IN ({$idList})";
           }
           else {
index 977fc60a9fd7a3f60b9c97963fb67cf2384d6f40..1abc63a044105f895444b6cfe7c20992d7cd7e22 100644 (file)
@@ -1822,8 +1822,14 @@ EOS;
    * @param $filter array filter to be applied indexed by operator
    * @param $type String type of field (not actually used - nor in api @todo )
    * @param $alias String alternative field name ('as') @todo- not actually used
+   * @param bool $returnSanitisedArray return a sanitised array instead of a clause
+   *  this is primarily so we can add filters @ the api level to the Query object based fields
+   *  @todo a better solutution would be for the query object to apply these filters based on the
+   *  api supported format (but we don't want to risk breakage in alpha stage & query class is scary
+   *  @todo @time of writing only IN & NOT IN are supported for the array style syntax (as test is
+   *  required to extend further & it may be the comments per above should be implemented
    */
-  public function createSQLFilter($fieldName, $filter, $type, $alias = NULL) {
+  public function createSQLFilter($fieldName, $filter, $type, $alias = NULL, $returnSanitisedArray = FALSE) {
     // http://issues.civicrm.org/jira/browse/CRM-9150 - stick with 'simple' operators for now
     // support for other syntaxes is discussed in ticket but being put off for now
     $acceptedSQLOperators = array('=', '<=', '>=', '>', '<', 'LIKE', "<>", "!=", "NOT LIKE", 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN');
@@ -1833,7 +1839,9 @@ EOS;
           // unary operators
           case 'IS NULL':
           case 'IS NOT NULL':
-            return (sprintf('%s %s', $fieldName, $operator));
+            if(!$returnSanitisedArray) {
+              return (sprintf('%s %s', $fieldName, $operator));
+            }
             break;
 
           // ternary operators
@@ -1842,7 +1850,9 @@ EOS;
             if (empty($criteria[0]) || empty($criteria[1])) {
               throw new exception("invalid criteria for $operator");
             }
-            return (sprintf('%s ' . $operator . ' "%s" AND "%s"', $fieldName, CRM_Core_DAO::escapeString($criteria[0]), CRM_Core_DAO::escapeString($criteria[1])));
+            if(!$returnSanitisedArray) {
+              return (sprintf('%s ' . $operator . ' "%s" AND "%s"', $fieldName, CRM_Core_DAO::escapeString($criteria[0]), CRM_Core_DAO::escapeString($criteria[1])));
+            }
             break;
 
           // n-ary operators
@@ -1855,13 +1865,18 @@ EOS;
               'CRM_Core_DAO',
               'escapeString'
             ), $criteria);
-            return (sprintf('%s %s ("%s")', $fieldName, $operator, implode('", "', $escapedCriteria)));
+            if(!$returnSanitisedArray) {
+              return (sprintf('%s %s ("%s")', $fieldName, $operator, implode('", "', $escapedCriteria)));
+            }
+            return $escapedCriteria;
             break;
 
           // binary operators
 
           default:
-            return(sprintf('%s %s "%s"', $fieldName, $operator, CRM_Core_DAO::escapeString($criteria)));
+            if(!$returnSanitisedArray) {
+              return(sprintf('%s %s "%s"', $fieldName, $operator, CRM_Core_DAO::escapeString($criteria)));
+            }
         }
       }
     }
index 14f6daa352ffbea6d20a59df98bc6410040b507a..149a7fb34b02ac8d816ebe18f3f1619644e89e69 100644 (file)
@@ -425,7 +425,20 @@ function _civicrm_api3_get_using_query_object($entity, $params, $additional_opti
   }
 
   $newParams = CRM_Contact_BAO_Query::convertFormValues($inputParams);
+  foreach ($newParams as &$newParam) {
+    if($newParam[1] == '='  && is_array($newParam[2])) {
+      // we may be looking at an attempt to use the 'IN' style syntax
+      // @todo at time of writing only 'IN' & 'NOT IN' are  supported for the array style syntax
+      $sqlFilter = CRM_Core_DAO::createSqlFilter($newParam[0], $params[$newParam[0]], 'String', NULL, TRUE);
+      if($sqlFilter) {
+        $newParam[1] = key($newParam[2]);
+        $newParam[2] = $sqlFilter;
+      }
+    }
+
+  }
   $skipPermissions = CRM_Utils_Array::value('check_permissions', $params)? 0 :1;
+
   list($entities, $options) = CRM_Contact_BAO_Query::apiQuery(
     $newParams,
     $returnProperties,
index f32706f41ddb3b8799a741ea3de7da6b220f9af4..b292b054fb99713c1747b7ee2730d04966650166 100644 (file)
@@ -409,6 +409,21 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
     $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
   }
+  /*
+   * Test that we can retrieve contacts using
+   * 'id' => array('IN' => array('3,4')) syntax
+  */
+  function testGetINIDArray() {
+    $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
+    $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
+    $c3 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'hh', 'last_name' => 'll', 'contact_type' => 'Individual'));
+    $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
+    $this->assertEquals(2, $result['count']);
+    $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
+    $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
+    $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
+    $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
+  }
   /*
    * Test variants on deleted behaviour
    */