From 3a48439179f881e4e45834d9874f82661d69d723 Mon Sep 17 00:00:00 2001 From: "deb.monish" Date: Wed, 7 Dec 2016 21:56:04 +0530 Subject: [PATCH] additional improvement and unit test --- CRM/Contact/BAO/Query.php | 37 +++++++- .../CRM/Contact/BAO/GroupContactTest.php | 91 +++++++++++++++++++ 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index 07d6d1f145..38ac4ec1b5 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -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 diff --git a/tests/phpunit/CRM/Contact/BAO/GroupContactTest.php b/tests/phpunit/CRM/Contact/BAO/GroupContactTest.php index 5dec7669fb..a613dc34af 100644 --- a/tests/phpunit/CRM/Contact/BAO/GroupContactTest.php +++ b/tests/phpunit/CRM/Contact/BAO/GroupContactTest.php @@ -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); + } + } + } -- 2.25.1