diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index d1aecf929b37..58e503e1b9ee 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -1014,9 +1014,9 @@ public function addHierarchicalElements() { foreach ($this->_returnProperties['location'] as $name => $elements) { $lCond = self::getPrimaryCondition($name); + $locationTypeId = is_numeric($name) ? NULL : array_search($name, $locationTypes); if (!$lCond) { - $locationTypeId = array_search($name, $locationTypes); if ($locationTypeId === FALSE) { continue; } @@ -1028,7 +1028,6 @@ public function addHierarchicalElements() { } $name = str_replace(' ', '_', $name); - $tName = "$name-location_type"; $ltName = "`$name-location_type`"; $this->_select["{$tName}_id"] = "`$tName`.id as `{$tName}_id`"; @@ -1039,7 +1038,6 @@ public function addHierarchicalElements() { $locationTypeName = $tName; $locationTypeJoin = array(); - $addAddress = FALSE; $addWhereCount = 0; foreach ($elements as $elementFullName => $dontCare) { $index++; @@ -1054,20 +1052,14 @@ public function addHierarchicalElements() { $addressCustomFieldIds[$cfID][$name] = 1; } } - //add address table only once + // add address table - doesn't matter if we do it mutliple times - it's the same data + // @todo ditch the double processing of addressJoin if ((in_array($elementCmpName, self::$_locationSpecificFields) || !empty($addressCustomFieldIds)) - && !$addAddress && !in_array($elementCmpName, array('email', 'phone', 'im', 'openid')) ) { - $tName = "$name-address"; - $aName = "`$name-address`"; - $this->_select["{$tName}_id"] = "`$tName`.id as `{$tName}_id`"; - $this->_element["{$tName}_id"] = 1; - $addressJoin = "\nLEFT JOIN civicrm_address $aName ON ($aName.contact_id = contact_a.id AND $aName.$lCond)"; - $this->_tables[$tName] = $addressJoin; + list($aName, $addressJoin) = $this->addAddressTable($name, $lCond); $locationTypeJoin[$tName] = " ( $aName.location_type_id = $ltName.id ) "; $processed[$aName] = 1; - $addAddress = TRUE; } $cond = $elementType = ''; @@ -6332,6 +6324,14 @@ protected function prepareOrderBy($sort, $sortOrder) { $direction = isset($orderByClauseParts[1]) ? $orderByClauseParts[1] : 'asc'; $fieldSpec = $this->getMetadataForRealField($field); + // This is a hacky add-in for primary address joins. Feel free to iterate as it is unit tested. + // @todo much more cleanup on location handling in addHierarchical elements. Potentially + // add keys to $this->fields to represent the actual keys for locations. + if (empty($fieldSpec) && substr($field, 0, 2) === '1-') { + $fieldSpec = $this->getMetadataForField(substr($field, 2)); + $this->addAddressTable('1-' . str_replace('civicrm_', '', $fieldSpec['table_name']), 'is_primary = 1'); + } + if ($this->_returnProperties === []) { if (!empty($fieldSpec['table_name']) && !isset($this->_tables[$fieldSpec['table_name']])) { $this->_tables[$fieldSpec['table_name']] = 1; @@ -6955,4 +6955,28 @@ protected function buildRelativeDateQuery(&$values) { } } + /** + * Add the address table into the query. + * + * @param string $tableKey + * @param string $joinCondition + * + * @return array + * - alias name + * - address join. + */ + protected function addAddressTable($tableKey, $joinCondition) { + $tName = "$tableKey-address"; + $aName = "`$tableKey-address`"; + $this->_select["{$tName}_id"] = "`$tName`.id as `{$tName}_id`"; + $this->_element["{$tName}_id"] = 1; + $addressJoin = "\nLEFT JOIN civicrm_address $aName ON ($aName.contact_id = contact_a.id AND $aName.$joinCondition)"; + $this->_tables[$tName] = $addressJoin; + + return [ + $aName, + $addressJoin + ]; + } + } diff --git a/CRM/Contact/Selector.php b/CRM/Contact/Selector.php index fc5bcc33170e..1736f0b20b8c 100644 --- a/CRM/Contact/Selector.php +++ b/CRM/Contact/Selector.php @@ -1228,11 +1228,7 @@ public function contactIDQuery($params, $sortID, $displayRelationshipType = NULL $queryOperator ); } - $value = $query->searchQuery(0, 0, $sort, - FALSE, FALSE, FALSE, - FALSE, FALSE - ); - return $value; + return $query->searchQuery(0, 0, $sort); } /** diff --git a/tests/phpunit/CRM/Contact/BAO/QueryTest.php b/tests/phpunit/CRM/Contact/BAO/QueryTest.php index a387a60777bd..abbe151527e6 100644 --- a/tests/phpunit/CRM/Contact/BAO/QueryTest.php +++ b/tests/phpunit/CRM/Contact/BAO/QueryTest.php @@ -712,6 +712,31 @@ public function testContactIDQuery($sortOrder) { $selector->contactIDQuery([], $sortOrder); } + /** + * Test the sorting on the contact ID query works with a profile search. + * + * Checking for lack of fatal. + */ + public function testContactIDQueryProfileSearchResults() { + $profile = $this->callAPISuccess('UFGroup', 'create', ['group_type' => 'Contact', 'name' => 'search', 'title' => 'search']); + $this->callAPISuccess('UFField', 'create', [ + 'uf_group_id' => $profile['id'], + 'field_name' => 'postal_code', + 'field_type' => 'Contact', + 'in_selector' => TRUE, + 'is_searchable' => TRUE, + 'label' => 'postal code', + 'visibility' => 'Public Pages and Listings', + ]); + $selector = new CRM_Contact_Selector(NULL, ['radio_ts' => 'ts_all', 'uf_group_id' => $profile['id']], NULL, ['sort_name' => 1]); + $selector->contactIDQuery([], '2_d'); + } + + /** + * Get search options to reflect how a UI search would look. + * + * @return array + */ public function getSortOptions() { return [ ['1_d'],