Skip to content

Commit 0a3f7f2

Browse files
CRM-17123 remove damaging OR from smart group query
Please add review comments to civicrm#8645 Note that in testing this I checked 1) searching in search builder with groups as a criteria (checked that correct groups show & only 'Added' ones) 2) Exporting - groups show per above when selected as an export field 3) Groups tab on a contact correctly shows added & removed groups 4) Api calls per tests 5) Manage groups - clicking through shows correct status for all members and it is possible to alter the group criteria to include 'Removed' and they show with the correct status Change-Id: I1304eaced73262f66030010bfcce05bc7d70d0b5
1 parent 8ad024a commit 0a3f7f2

File tree

4 files changed

+61
-32
lines changed

4 files changed

+61
-32
lines changed

CRM/Contact/BAO/Group.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ public static function checkPermission($id, $excludeHidden = FALSE) {
346346
* @return CRM_Contact_BAO_Group|NULL
347347
* The new group BAO (if created)
348348
*/
349-
public static function &create(&$params) {
349+
public static function create(&$params) {
350350

351351
if (!empty($params['id'])) {
352352
CRM_Utils_Hook::pre('edit', 'Group', $params['id'], $params);
@@ -460,7 +460,6 @@ public static function &create(&$params) {
460460
}
461461

462462
if (!empty($params['organization_id'])) {
463-
$groupOrg = array();
464463
$groupOrg = $params;
465464
$groupOrg['group_id'] = $group->id;
466465
CRM_Contact_BAO_GroupOrganization::add($groupOrg);

CRM/Contact/BAO/GroupContact.php

+2-6
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public static function getGroupList($contactId = 0, $visibility = FALSE) {
331331
* @return array|int $values
332332
* the relevant data object values for the contact or the total count when $count is TRUE
333333
*/
334-
public static function &getContactGroup(
334+
public static function getContactGroup(
335335
$contactId,
336336
$status = NULL,
337337
$numGroupContact = NULL,
@@ -356,7 +356,7 @@ public static function &getContactGroup(
356356
civicrm_subscription_history.method as method';
357357
}
358358

359-
$where = " WHERE contact_a.id = %1 AND civicrm_group.is_active = 1";
359+
$where = " WHERE contact_a.id = %1 AND civicrm_group.is_active = 1 AND saved_search_id IS NULL";
360360

361361
if ($excludeHidden) {
362362
$where .= " AND civicrm_group.is_hidden = 0 ";
@@ -386,10 +386,6 @@ public static function &getContactGroup(
386386

387387
$from = CRM_Contact_BAO_Query::fromClause($tables);
388388

389-
//CRM-16945: seems hackish but as per CRM-16483 of using group criteria for Search Builder it is mandatory
390-
//to include group_contact_cache clause when group table is present, so following code remove duplicacy
391-
$from = str_replace("OR civicrm_group.id = civicrm_group_contact_cache.group_id", 'AND civicrm_group.saved_search_id IS NULL', $from);
392-
393389
$where .= " AND $permission ";
394390

395391
if ($onlyPublicGroups) {

CRM/Contact/BAO/Query.php

+57-23
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,10 @@ public function buildParamsLookup() {
586586
if (!array_key_exists($value[0], $this->_paramLookup)) {
587587
$this->_paramLookup[$value[0]] = array();
588588
}
589-
$this->_paramLookup[$value[0]][] = $value;
589+
if ($value[0] !== 'group') {
590+
// Just trying to unravel how group interacts here! This whole function is wieid.
591+
$this->_paramLookup[$value[0]][] = $value;
592+
}
590593
}
591594
}
592595

@@ -869,9 +872,20 @@ public function selectClause($apiEntity = NULL) {
869872
}
870873
elseif ($name === 'groups') {
871874
$this->_useGroupBy = TRUE;
872-
$this->_select[$name] = "GROUP_CONCAT(DISTINCT(civicrm_group.title)) as groups";
875+
// Duplicates will be created here but better to sort them out in php land.
876+
$this->_select[$name] = "
877+
CONCAT_WS(',',
878+
GROUP_CONCAT(DISTINCT IF(civicrm_group_contact.status = 'Added', civicrm_group_contact.group_id, '')),
879+
GROUP_CONCAT(DISTINCT civicrm_group_contact_cache.group_id)
880+
)
881+
as groups";
873882
$this->_element[$name] = 1;
874-
$this->_tables['civicrm_group'] = 1;
883+
$this->_tables['civicrm_group_contact'] = 1;
884+
$this->_tables['civicrm_group_contact_cache'] = 1;
885+
$this->_pseudoConstantsSelect["{$name}"] = array(
886+
'pseudoField' => "groups",
887+
'idCol' => "groups",
888+
);
875889
}
876890
elseif ($name === 'notes') {
877891
// if note field is subject then return subject else body of the note
@@ -1367,6 +1381,7 @@ public function query($count = FALSE, $sortByChar = FALSE, $groupContacts = FALS
13671381
$this->_paramLookup['group'][0][1] = key($value);
13681382
}
13691383

1384+
// Presumably the lines below come into manage groups screen.
13701385
// make sure there is only one element
13711386
// this is used when we are running under smog and need to know
13721387
// how the contact was added (CRM-1203)
@@ -2511,16 +2526,6 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima
25112526
);
25122527
}
25132528

2514-
// add group_contact and group_contact_cache table if group table is present
2515-
if (!empty($tables['civicrm_group'])) {
2516-
if (empty($tables['civicrm_group_contact'])) {
2517-
$tables['civicrm_group_contact'] = " LEFT JOIN civicrm_group_contact ON civicrm_group_contact.contact_id = contact_a.id AND civicrm_group_contact.status = 'Added' ";
2518-
}
2519-
if (empty($tables['civicrm_group_contact_cache'])) {
2520-
$tables['civicrm_group_contact_cache'] = " LEFT JOIN civicrm_group_contact_cache ON civicrm_group_contact_cache.contact_id = contact_a.id ";
2521-
}
2522-
}
2523-
25242529
// add group_contact and group table is subscription history is present
25252530
if (!empty($tables['civicrm_subscription_history']) && empty($tables['civicrm_group'])) {
25262531
$tables = array_merge(array(
@@ -2635,7 +2640,7 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima
26352640
continue;
26362641

26372642
case 'civicrm_group':
2638-
$from .= " $side JOIN civicrm_group ON (civicrm_group.id = civicrm_group_contact.group_id OR civicrm_group.id = civicrm_group_contact_cache.group_id) ";
2643+
$from .= " $side JOIN civicrm_group ON civicrm_group.id = civicrm_group_contact.group_id ";
26392644
continue;
26402645

26412646
case 'civicrm_group_contact':
@@ -2875,11 +2880,11 @@ public function includeContactSubTypes($value, $grouping, $op = 'LIKE') {
28752880
}
28762881

28772882
/**
2878-
* Where / qill clause for groups
2883+
* Where / qill clause for groups.
28792884
*
28802885
* @param $values
28812886
*/
2882-
public function group(&$values) {
2887+
public function group($values) {
28832888
list($name, $op, $value, $grouping, $wildcard) = $values;
28842889

28852890
// If the $value is in OK (operator as key) array format we need to extract the key as operator and value first
@@ -2907,8 +2912,7 @@ public function group(&$values) {
29072912
}
29082913

29092914
$groupIds = NULL;
2910-
$names = array();
2911-
$isSmart = FALSE;
2915+
29122916
$isNotOp = ($op == 'NOT IN' || $op == '!=');
29132917

29142918
$statii = array();
@@ -2926,7 +2930,8 @@ public function group(&$values) {
29262930
$statii[] = '"Added"';
29272931
}
29282932

2929-
$skipGroup = FALSE;
2933+
$ssClause = $this->addGroupContactCache($value, NULL, "contact_a", $op);
2934+
$isSmart = (!$ssClause) ? FALSE : TRUE;
29302935
if (!is_array($value) &&
29312936
count($statii) == 1 &&
29322937
$statii[0] == '"Added"' &&
@@ -2936,9 +2941,6 @@ public function group(&$values) {
29362941
$isSmart = TRUE;
29372942
}
29382943
}
2939-
2940-
$ssClause = $this->addGroupContactCache($value, NULL, "contact_a", $op);
2941-
$isSmart = (!$ssClause) ? FALSE : $isSmart;
29422944
$groupClause = NULL;
29432945

29442946
if (!$isSmart) {
@@ -3035,6 +3037,9 @@ public function addGroupContactCache($groups, $tableAlias = NULL, $joinTable = "
30353037
CRM_Contact_BAO_GroupContactCache::load($group);
30363038
}
30373039
}
3040+
if ($group->N == 0) {
3041+
return NULL;
3042+
}
30383043

30393044
if (!$tableAlias) {
30403045
$tableAlias = "`civicrm_group_contact_cache_";
@@ -4253,8 +4258,9 @@ public static function getPrimaryCondition($value) {
42534258
public static function getQuery($params = NULL, $returnProperties = NULL, $count = FALSE) {
42544259
$query = new CRM_Contact_BAO_Query($params, $returnProperties);
42554260
list($select, $from, $where, $having) = $query->query();
4261+
$groupBy = ($query->_useGroupBy) ? 'GROUP BY contact_a.id' : '';
42564262

4257-
return "$select $from $where $having";
4263+
return "$select $from $where $groupBy $having";
42584264
}
42594265

42604266
/**
@@ -5681,6 +5687,10 @@ public function convertToPseudoNames(&$dao, $return = FALSE, $usedForAPI = FALSE
56815687

56825688
if (is_object($dao) && property_exists($dao, $value['idCol'])) {
56835689
$val = $dao->$value['idCol'];
5690+
if ($key == 'groups') {
5691+
$dao->groups = $this->convertGroupIDStringToLabelString($dao, $val);
5692+
return;
5693+
}
56845694

56855695
if (CRM_Utils_System::isNull($val)) {
56865696
$dao->$key = NULL;
@@ -6085,4 +6095,28 @@ public function setQillAndWhere($name, $op, $value, $grouping, $field) {
60856095
));
60866096
}
60876097

6098+
/**
6099+
* Convert a string of group IDs to a string of group labels.
6100+
*
6101+
* The original string may include duplicates and groups the user does not have
6102+
* permission to see.
6103+
*
6104+
* @param CRM_Core_DAO $dao
6105+
* @param string $val
6106+
*
6107+
* @return string
6108+
*/
6109+
public function convertGroupIDStringToLabelString(&$dao, $val) {
6110+
$groupIDs = explode(',', $val);
6111+
6112+
// The pseudoConstant function does not actually cache.
6113+
static $allGroups;
6114+
if (!$allGroups) {
6115+
$allGroups = CRM_Core_PseudoConstant::group();
6116+
}
6117+
// Note that groups that the user does not have permission to will be excluded (good).
6118+
$groups = array_intersect_key($allGroups, array_flip($groupIDs));
6119+
return implode(', ', $groups);
6120+
}
6121+
60886122
}

CRM/Contact/Selector.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1189,7 +1189,7 @@ private static function &_getColumnHeaders() {
11891189
/**
11901190
* @return CRM_Contact_BAO_Query
11911191
*/
1192-
public function &getQuery() {
1192+
public function getQuery() {
11931193
return $this->_query;
11941194
}
11951195

0 commit comments

Comments
 (0)