additional improvement and unit test
authordeb.monish <monish.deb@webaccessglobal.com>
Wed, 7 Dec 2016 16:26:04 +0000 (21:56 +0530)
committerdeb.monish <monish.deb@webaccessglobal.com>
Fri, 9 Dec 2016 05:48:28 +0000 (11:18 +0530)
CRM/Contact/BAO/Query.php
tests/phpunit/CRM/Contact/BAO/GroupContactTest.php

index 07d6d1f145bd8e470e0f81cd8a80d1e51501e49a..38ac4ec1b5a8e4a50f5dc0165a8bac53d4720996 100644 (file)
@@ -2956,14 +2956,23 @@ class CRM_Contact_BAO_Query {
       }
       $this->_tables[$gcTable] = $this->_whereTables[$gcTable] = " LEFT JOIN civicrm_group_contact {$gcTable} ON (" . implode(' AND ', $joinClause) . ")";
       if (strpos($op, 'IN') !== FALSE) {
-        $groupClause[] = "{$gcTable}.group_id $op ( $groupIds )";
+        $clause = "{$gcTable}.group_id $op ( $groupIds ) %s ";
       }
       elseif ($op == '!=') {
-        $groupClause[] = "{$gcTable}.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact cgc WHERE cgc.group_id = $groupIds)";
+        $clause = "{$gcTable}.contact_id NOT IN (SELECT contact_id FROM civicrm_group_contact cgc WHERE cgc.group_id = $groupIds %s)";
       }
       else {
-        $groupClause[] = "{$gcTable}.group_id $op $groupIds";
+        $clause = "{$gcTable}.group_id $op $groupIds %s ";
       }
+
+      // include child groups IDs if any
+      $childGroupIds = self::getChildGroupIds($regularGroupIDs);
+      $childClause = '';
+      if (count($childGroupIds)) {
+        $gcTable = ($op == '!=') ? 'cgc' : $gcTable;
+        $childClause = " OR {$gcTable}.group_id IN (" . implode(',', $childGroupIds) . ") ";
+      }
+      $groupClause[] = sprintf($clause, $childClause);
     }
 
     //CRM-19589: contact(s) removed from a Smart Group, resides in civicrm_group_contact table
@@ -2981,6 +2990,28 @@ class CRM_Contact_BAO_Query {
     }
   }
 
+  /**
+   * Get child group ids
+   *
+   * @param array $ids
+   *    Parent Group IDs
+   *
+   * @return array
+   */
+  public static function getChildGroupIds($ids) {
+    $notFound = FALSE;
+    $childGroupIds = array();
+    foreach ($ids as $id) {
+      $childId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $id, 'children');
+      while (!empty($childId)) {
+        $childGroupIds[] = $childId;
+        $childId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $childId, 'children');
+      }
+    }
+
+    return $childGroupIds;
+  }
+
   /**
    * Function translates selection of group type into a list of groups.
    * @param $value
index 5dec7669fb5cf74755d614b186f0a02c46a29a76..a613dc34afd0631e2724b144a16f3df15c0280a0 100644 (file)
@@ -155,4 +155,95 @@ class CRM_Contact_BAO_GroupContactTest extends CiviUnitTestCase {
     $this->assertEquals(array(), array_diff($validChildContactIds, $resultChildContactIds), 'Check that the difference between two arrays should be blank array');
   }
 
+
+  /**
+   *  CRM-19698: Test case for combine contact search in regular and smart group
+   */
+  public function testContactCombineGroupSearch() {
+    // create regular group based
+    $regularGroup = $this->callAPISuccess('Group', 'create', array(
+      'title' => 'Regular Group',
+      'description' => 'Regular Group',
+      'visibility' => 'User and User Admin Only',
+      'is_active' => 1,
+    ));
+
+    // Create contact with Gender - Male
+    $contact1 = $this->individualCreate(array(
+      'gender_id' => "Male",
+    ));
+
+    // Create contact with Gender - Male and in regular group
+    $contact2 = $this->individualCreate(array(
+      'group' => array($regularGroup['id'] => 1),
+      'gender_id' => "Male",
+    ), 1);
+
+    // Create contact with Gender - Female and in regular group
+    $contact3 = $this->individualCreate(array(
+      'group' => array($regularGroup['id'] => 1),
+      'gender_id' => "Female",
+    ), 1);
+
+    // create smart group based on saved criteria Gender = Male
+    $batch = $this->callAPISuccess('SavedSearch', 'create', array(
+      'form_values' => 'a:1:{i:0;a:5:{i:0;s:9:"gender_id";i:1;s:1:"=";i:2;i:2;i:3;i:0;i:4;i:0;}}',
+    ));
+    $smartGroup = $this->callAPISuccess('Group', 'create', array(
+      'title' => 'Smart Group',
+      'description' => 'Smart Group',
+      'visibility' => 'User and User Admin Only',
+      'saved_search_id' => $batch['id'],
+      'is_active' => 1,
+    ));
+
+    $useCases = array(
+      //Case 1: Find all contacts in regular group
+      array(
+        'form_value' => array('group' => $regularGroup['id']),
+        'expected_count' => 2,
+        'operator' => 'AND',
+        'expected_contact' => array($contact2, $contact3),
+      ),
+      //Case 2: Find all contacts in smart group
+      array(
+        'form_value' => array('group' => $smartGroup['id']),
+        'expected_count' => 2,
+        'operator' => 'AND',
+        'expected_contact' => array($contact1, $contact2),
+      ),
+      //Case 3: Find all contacts in regular group AND smart group
+      array(
+        'form_value' => array('group' => array('IN' => array($regularGroup['id'], $smartGroup['id']))),
+        'expected_count' => 1,
+        'operator' => 'AND',
+        'expected_contact' => array($contact2),
+      ),
+      //Case 4: Find all contacts in regular group OR smart group
+      array(
+        'form_value' => array('group' => array('IN' => array($regularGroup['id'], $smartGroup['id']))),
+        'expected_count' => 3,
+        'operator' => 'OR',
+        'expected_contact' => array($contact1, $contact2, $contact3),
+      ),
+    );
+    foreach ($useCases as $case) {
+      $query = new CRM_Contact_BAO_Query(
+        CRM_Contact_BAO_Query::convertFormValues($case['form_value']),
+        NULL, NULL,
+        FALSE, FALSE, 1,
+        FALSE, TRUE,
+        TRUE, NULL,
+        $case['operator']
+      );
+      list($select, $from, $where, $having) = $query->query();
+      $groupContacts = CRM_Core_DAO::executeQuery("SELECT DISTINCT contact_a.id $from $where")->fetchAll();
+      foreach ($groupContacts as $key => $value) {
+        $groupContacts[$key] = $value['id'];
+      }
+      $this->assertEquals($case['expected_count'], count($groupContacts));
+      $this->checkArrayEquals($case['expected_contact'], $groupContacts);
+    }
+  }
+
 }