* Where / qill clause for groups.
*
* @param $values
+ *
+ * @throws \CRM_Core_Exception
*/
public function group($values) {
list($name, $op, $value, $grouping, $wildcard) = $values;
$isNotOp = ($op == 'NOT IN' || $op == '!=');
$statusJoinClause = $this->getGroupStatusClause($grouping);
+ // If we are searching for 'Removed' contacts then despite it being a smart group we only care about the group_contact table.
+ $isGroupStatusSearch = (!empty($this->getSelectedGroupStatuses($grouping)) && $this->getSelectedGroupStatuses($grouping) !== ["'Added'"]);
$groupClause = [];
- if ($hasNonSmartGroups || empty($value)) {
+ if ($hasNonSmartGroups || empty($value) || $isGroupStatusSearch) {
// include child groups IDs if any
$childGroupIds = (array) CRM_Contact_BAO_Group::getChildGroupIds($regularGroupIDs);
foreach ($childGroupIds as $key => $id) {
}
if (empty($regularGroupIDs)) {
- $regularGroupIDs = [0];
+ if ($isGroupStatusSearch) {
+ $regularGroupIDs = $smartGroupIDs;
+ }
+ // If it is still empty we want a filter that blocks all results.
+ if (empty($regularGroupIDs)) {
+ $regularGroupIDs = [0];
+ }
}
// if $regularGroupIDs is populated with regular child group IDs
}
//CRM-19589: contact(s) removed from a Smart Group, resides in civicrm_group_contact table
- $groupContactCacheClause = '';
- if (count($smartGroupIDs) || empty($value)) {
+ // If we are only searching for Removed or Pending contacts we don't need to resolve the smart group
+ // as that info is in the group_contact table.
+ if ((count($smartGroupIDs) || empty($value)) && !$isGroupStatusSearch) {
$this->_groupUniqueKey = uniqid();
$this->_groupKeys[] = $this->_groupUniqueKey;
$gccTableAlias = "civicrm_group_contact_cache_{$this->_groupUniqueKey}";
$this->assertEquals(2, $resultDAO->N);
}
+ /**
+ * Test we can narrow a group get by status.
+ *
+ * @throws \Exception
+ */
+ public function testGetByGroupWithStatusSmartGroup() {
+ $groupID = $this->smartGroupCreate();
+ // This means they are actually all hard-added, which is fine for this purpose.
+ $this->groupContactCreate($groupID, 3);
+ $groupContactID = $this->callAPISuccessGetSingle('GroupContact', ['group_id' => $groupID, 'options' => ['limit' => 1]])['id'];
+ $this->callAPISuccess('GroupContact', 'create', ['id' => $groupContactID, 'status' => 'Removed']);
+
+ $queryObj = new CRM_Contact_BAO_Query([['group', '=', $groupID, 0, 0], ['group_contact_status', 'IN', ['Removed' => 1], 0, 0]]);
+ $resultDAO = $queryObj->searchQuery();
+ $this->assertEquals(1, $resultDAO->N);
+ }
+
/**
* Test the group contact clause does not contain an OR.
*
* The search should return 3 contacts - 2 households in the smart group of
* Contact Type = Household and one Individual hard-added to it. The
* Household that meets both criteria should be returned once.
+ *
+ * @throws \Exception
*/
public function testGroupClause() {
$this->householdCreate();
*
* @param array $smartGroupParams
* @param array $groupParams
+ * @param string $contactType
+ *
* @return int
*/
- public function smartGroupCreate($smartGroupParams = array(), $groupParams = array()) {
- $smartGroupParams = array_merge(array(
- 'formValues' => array('contact_type' => array('IN' => array('Household'))),
- ),
- $smartGroupParams);
+ public function smartGroupCreate($smartGroupParams = [], $groupParams = [], $contactType = 'Household') {
+ $smartGroupParams = array_merge([
+ 'formValues' => ['contact_type' => ['IN' => [$contactType]]],
+ ],
+ $smartGroupParams);
$savedSearch = CRM_Contact_BAO_SavedSearch::create($smartGroupParams);
$groupParams['saved_search_id'] = $savedSearch->id;