From 744050b03bb40310b3e6108c33a4376adb4f01b3 Mon Sep 17 00:00:00 2001 From: Jitendra Purohit <jitendra@fuzion.co.nz> Date: Fri, 16 Feb 2018 12:43:45 +0530 Subject: [PATCH] CRM-21776: Ensure from clause adds custom table when search query is ordered by a custom field --- CRM/Contact/BAO/Query.php | 9 ++++ tests/phpunit/CRM/Contact/SelectorTest.php | 53 ++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index 5435aa3c2fb6..bcc3ee00a58e 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -6418,6 +6418,15 @@ protected function prepareOrderBy($sort, $sortByChar, $sortOrder, $additionalFro break; default: + $cfID = CRM_Core_BAO_CustomField::getKeyID($field); + // add to cfIDs array if not present + if (!empty($cfID) && !array_key_exists($cfID, $this->_cfIDs)) { + $this->_cfIDs[$cfID] = array(); + $this->_customQuery = new CRM_Core_BAO_CustomQuery($this->_cfIDs, TRUE, $this->_locationSpecificCustomFields); + $this->_customQuery->query(); + $this->_select = array_merge($this->_select, $this->_customQuery->_select); + $this->_tables = array_merge($this->_tables, $this->_customQuery->_tables); + } foreach ($this->_pseudoConstantsSelect as $key => $pseudoConstantMetadata) { // By replacing the join to the option value table with the mysql construct // ORDER BY field('contribution_status_id', 2,1,4) diff --git a/tests/phpunit/CRM/Contact/SelectorTest.php b/tests/phpunit/CRM/Contact/SelectorTest.php index 8aa95640b09c..58e41583aee1 100644 --- a/tests/phpunit/CRM/Contact/SelectorTest.php +++ b/tests/phpunit/CRM/Contact/SelectorTest.php @@ -173,6 +173,59 @@ public function testContactIDQuery() { $searchOBJ->contactIDQuery($params, '1_u'); } + /** + * Test if custom table is added in from clause when + * search results are ordered by a custom field. + */ + public function testSelectorQueryOrderByCustomField() { + //Search for any params. + $params = [[ + 0 => 'country-1', + 1 => '=', + 2 => '1228', + 3 => 1, + 4 => 0, + ]]; + + //Create a test custom group and field. + $customGroup = $this->callAPISuccess('CustomGroup', 'create', array( + 'title' => "test custom group", + 'extends' => "Individual", + )); + $cgTableName = $customGroup['values'][$customGroup['id']]['table_name']; + $customField = $this->callAPISuccess('CustomField', 'create', array( + 'custom_group_id' => $customGroup['id'], + 'label' => "test field", + 'html_type' => "Text", + )); + $customFieldId = $customField['id']; + + //Sort by the custom field created above. + $sortParams = array( + 1 => array( + 'name' => 'test field', + 'sort' => "custom_{$customFieldId}", + ), + ); + $sort = new CRM_Utils_Sort($sortParams, '1_d'); + + //Form a query to order by a custom field. + $query = new CRM_Contact_BAO_Query($params, + CRM_Contact_BAO_Query::NO_RETURN_PROPERTIES, + NULL, FALSE, FALSE, 1, + FALSE, TRUE, TRUE, NULL, + 'AND' + ); + $query->searchQuery(0, 0, $sort, + FALSE, FALSE, FALSE, + FALSE, FALSE + ); + //Check if custom table is included in $query->_tables. + $this->assertTrue(in_array($cgTableName, array_keys($query->_tables))); + //Assert if from clause joins the custom table. + $this->assertTrue(strpos($query->_fromClause, $cgTableName) !== FALSE); + } + /** * Get the default select string since this is generally consistent. */