From b3e1c09d7cdfc826711be0a7867997eb4a4363e7 Mon Sep 17 00:00:00 2001 From: jitendrapurohit Date: Thu, 2 Feb 2017 17:06:01 +0530 Subject: [PATCH] CRM-4287: Contact search for email address shows only primary email matches as results --- CRM/Admin/Form/Setting/Search.php | 1 + CRM/Contact/BAO/Query.php | 11 ++-- settings/Search.setting.php | 14 ++++++ templates/CRM/Admin/Form/Setting/Search.tpl | 6 +++ tests/phpunit/CRM/Contact/BAO/QueryTest.php | 56 +++++++++++++++++++++ 5 files changed, 85 insertions(+), 3 deletions(-) diff --git a/CRM/Admin/Form/Setting/Search.php b/CRM/Admin/Form/Setting/Search.php index 006aca2de0..e0f279d2b7 100644 --- a/CRM/Admin/Form/Setting/Search.php +++ b/CRM/Admin/Form/Setting/Search.php @@ -49,6 +49,7 @@ class CRM_Admin_Form_Setting_Search extends CRM_Admin_Form_Setting { 'includeOrderByClause' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, 'smartGroupCacheTimeout' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, 'defaultSearchProfileID' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, + 'searchPrimaryEmailOnly' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, ); /** diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index d7e47b6520..e3ad0230e4 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -514,7 +514,7 @@ class CRM_Contact_BAO_Query { CRM_Financial_BAO_FinancialType::buildPermissionedClause($this->_whereClause, $component); } - $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode); + $this->_fromClause = self::fromClause($this->_tables, NULL, NULL, $this->_primaryLocation, $this->_mode, $apiEntity); $this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode); $this->openedSearchPanes(TRUE); @@ -2528,11 +2528,12 @@ class CRM_Contact_BAO_Query { * * @param bool $primaryLocation * @param int $mode + * @param string|NULL $apiEntity * * @return string * the from clause */ - public static function fromClause(&$tables, $inner = NULL, $right = NULL, $primaryLocation = TRUE, $mode = 1) { + public static function fromClause(&$tables, $inner = NULL, $right = NULL, $primaryLocation = TRUE, $mode = 1, $apiEntity = NULL) { $from = ' FROM civicrm_contact contact_a'; if (empty($tables)) { @@ -2639,7 +2640,11 @@ class CRM_Contact_BAO_Query { continue; case 'civicrm_email': - $from .= " $side JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id AND civicrm_email.is_primary = 1) "; + $searchPrimary = ''; + if (Civi::settings()->get('searchPrimaryEmailOnly') || $apiEntity) { + $searchPrimary = " AND civicrm_email.is_primary = 1"; + } + $from .= " $side JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id) {$searchPrimary}"; continue; case 'civicrm_im': diff --git a/settings/Search.setting.php b/settings/Search.setting.php index 71f6e677d6..560288635e 100644 --- a/settings/Search.setting.php +++ b/settings/Search.setting.php @@ -197,4 +197,18 @@ return array( 'description' => 'If set, this will be the default profile used for contact search.', 'help_text' => NULL, ), + 'searchPrimaryEmailOnly' => array( + 'group_name' => 'Search Preferences', + 'group' => 'Search Preferences', + 'name' => 'searchPrimaryEmailOnly', + 'type' => 'Boolean', + 'quick_form_type' => 'YesNo', + 'default' => 1, + 'add' => '4.7', + 'title' => 'Search Primary Email Only', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => 'If enabled, only primary email address will be included when users search by Email. Secondary emails will only be displayed in Full Text search results. Disabling this feature will allow searching by any emails attached to the contact.', + 'help_text' => NULL, + ), ); diff --git a/templates/CRM/Admin/Form/Setting/Search.tpl b/templates/CRM/Admin/Form/Setting/Search.tpl index e0f68826e5..ea31c6e4db 100644 --- a/templates/CRM/Admin/Form/Setting/Search.tpl +++ b/templates/CRM/Admin/Form/Setting/Search.tpl @@ -37,6 +37,12 @@ {$form.includeEmailInName.html}
{ts}If enabled, email addresses are automatically included when users search by Name. Disabling this feature will speed up search significantly for larger databases, but users will need to use the Email search fields (from Advanced Search, Search Builder, or Profiles) to find contacts by email address.{/ts} + + {$form.searchPrimaryEmailOnly.label} + {$form.searchPrimaryEmailOnly.html}
+ {ts}If enabled, only primary email address will be included when users search by Email. Secondary emails will only be included in Full Text search results. Disabling this feature will allow searching by any emails attached to the contact.{/ts} + + {$form.includeNickNameInName.label} {$form.includeNickNameInName.html}
diff --git a/tests/phpunit/CRM/Contact/BAO/QueryTest.php b/tests/phpunit/CRM/Contact/BAO/QueryTest.php index 5c014f30b8..965a3a8f8b 100644 --- a/tests/phpunit/CRM/Contact/BAO/QueryTest.php +++ b/tests/phpunit/CRM/Contact/BAO/QueryTest.php @@ -151,6 +151,62 @@ class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase { } } + /** + * Test searchByPrimaryEmailOnly setting. + */ + public function testSearchByPrimaryEmailOnly() { + $contactID = $this->individualCreate(); + $params = array( + 'contact_id' => $contactID, + 'email' => 'primary@example.com', + 'is_primary' => 1, + ); + $this->callAPISuccess('email', 'create', $params); + + unset($params['is_primary']); + $params['email'] = 'secondary@team.com'; + $this->callAPISuccess('email', 'create', $params); + + foreach (array(0, 1) as $searchPrimary) { + Civi::settings()->set('searchPrimaryEmailOnly', $searchPrimary); + + $params = array( + 0 => array( + 0 => 'email', + 1 => 'LIKE', + 2 => 'secondary@example.com', + 3 => 0, + 4 => 1, + ), + ); + $returnProperties = array( + 'contact_type' => 1, + 'contact_sub_type' => 1, + 'sort_name' => 1, + ); + + $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); + $resultDAO = $queryObj->searchQuery(0, 0, NULL, + FALSE, FALSE, + FALSE, FALSE, + FALSE); + + if ($searchPrimary) { + $this->assertEquals($resultDAO->N, 0); + } + else { + //Assert secondary email gets included in search results. + while ($resultDAO->fetch()) { + $this->assertEquals('secondary@example.com', $resultDAO->email); + } + } + + // API should always return primary email. + $result = $this->callAPISuccess('Contact', 'get', array('contact_id' => $contactID)); + $this->assertEquals('primary@example.com', $result['values'][$contactID]['email']); + } + } + /** * CRM-14263 search builder failure with search profile & address in criteria * We are retrieving primary here - checking the actual sql seems super prescriptive - but since the massive query object has -- 2.25.1