From b3e1c09d7cdfc826711be0a7867997eb4a4363e7 Mon Sep 17 00:00:00 2001 From: jitendrapurohit Date: Thu, 2 Feb 2017 17:06:01 +0530 Subject: [PATCH 1/5] 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 006aca2de037..e0f279d2b7a4 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 d7e47b65203b..e3ad0230e4cc 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -514,7 +514,7 @@ public function initialize($apiEntity = NULL) { 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 @@ public static function getWhereClause($params, $fields, &$tables, &$whereTables, * * @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 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima 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 71f6e677d6dc..560288635e97 100644 --- a/settings/Search.setting.php +++ b/settings/Search.setting.php @@ -197,4 +197,18 @@ '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 e0f68826e537..ea31c6e4db8a 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 5c014f30b8e6..965a3a8f8bef 100644 --- a/tests/phpunit/CRM/Contact/BAO/QueryTest.php +++ b/tests/phpunit/CRM/Contact/BAO/QueryTest.php @@ -151,6 +151,62 @@ public function testSearchProfileHomeCityNoResultsCRM14263() { } } + /** + * 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 From 9349bcf79da55322a0cb3ab727422ab47903abed Mon Sep 17 00:00:00 2001 From: jitendrapurohit Date: Fri, 3 Feb 2017 12:36:10 +0530 Subject: [PATCH 2/5] include phone, address, etc --- CRM/Admin/Form/Setting/Search.php | 2 +- CRM/Contact/BAO/Query.php | 26 ++++++++++----------- settings/Search.setting.php | 8 +++---- templates/CRM/Admin/Form/Setting/Search.tpl | 8 +++---- tests/phpunit/CRM/Contact/BAO/QueryTest.php | 6 ++--- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/CRM/Admin/Form/Setting/Search.php b/CRM/Admin/Form/Setting/Search.php index e0f279d2b7a4..8435da84269a 100644 --- a/CRM/Admin/Form/Setting/Search.php +++ b/CRM/Admin/Form/Setting/Search.php @@ -49,7 +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, + 'searchPrimaryLocTypes' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, ); /** diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index e3ad0230e4cc..41c742d4d781 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -2624,31 +2624,29 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima } continue; } + $searchPrimary = ''; + if (Civi::settings()->get('searchPrimaryLocTypes') || $apiEntity) { + $searchPrimary = " AND {$name}.is_primary = 1"; + } switch ($name) { case 'civicrm_address': - if ($primaryLocation) { - $from .= " $side JOIN civicrm_address ON ( contact_a.id = civicrm_address.contact_id AND civicrm_address.is_primary = 1 )"; - } - else { - //CRM-14263 further handling of address joins further down... - $from .= " $side JOIN civicrm_address ON ( contact_a.id = civicrm_address.contact_id ) "; + //CRM-14263 further handling of address joins further down... + if (!$primaryLocation) { + $searchPrimary = ''; } + $from .= " $side JOIN civicrm_address ON ( contact_a.id = civicrm_address.contact_id {$searchPrimary} )"; continue; case 'civicrm_phone': - $from .= " $side JOIN civicrm_phone ON (contact_a.id = civicrm_phone.contact_id AND civicrm_phone.is_primary = 1) "; + $from .= " $side JOIN civicrm_phone ON (contact_a.id = civicrm_phone.contact_id {$searchPrimary}) "; continue; case 'civicrm_email': - $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}"; + $from .= " $side JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id {$searchPrimary})"; continue; case 'civicrm_im': - $from .= " $side JOIN civicrm_im ON (contact_a.id = civicrm_im.contact_id AND civicrm_im.is_primary = 1) "; + $from .= " $side JOIN civicrm_im ON (contact_a.id = civicrm_im.contact_id {$searchPrimary}) "; continue; case 'im_provider': @@ -2658,7 +2656,7 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima continue; case 'civicrm_openid': - $from .= " $side JOIN civicrm_openid ON ( civicrm_openid.contact_id = contact_a.id AND civicrm_openid.is_primary = 1 )"; + $from .= " $side JOIN civicrm_openid ON ( civicrm_openid.contact_id = contact_a.id {$searchPrimary} )"; continue; case 'civicrm_worldregion': diff --git a/settings/Search.setting.php b/settings/Search.setting.php index 560288635e97..d970d08a6698 100644 --- a/settings/Search.setting.php +++ b/settings/Search.setting.php @@ -197,18 +197,18 @@ 'description' => 'If set, this will be the default profile used for contact search.', 'help_text' => NULL, ), - 'searchPrimaryEmailOnly' => array( + 'searchPrimaryLocTypes' => array( 'group_name' => 'Search Preferences', 'group' => 'Search Preferences', - 'name' => 'searchPrimaryEmailOnly', + 'name' => 'searchPrimaryLocTypes', 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 1, 'add' => '4.7', - 'title' => 'Search Primary Email Only', + 'title' => 'Search Primary Location Types 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.', + 'description' => 'If enabled, only primary location types(email, phone, etc.) will be included in Basic and Advanced Search results. Disabling this feature will allow users to search by any location type values 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 ea31c6e4db8a..5c50ae91838f 100644 --- a/templates/CRM/Admin/Form/Setting/Search.tpl +++ b/templates/CRM/Admin/Form/Setting/Search.tpl @@ -37,10 +37,10 @@ {$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.searchPrimaryLocTypes.label} + {$form.searchPrimaryLocTypes.html}
+ {ts}If enabled, only primary location types(email, phone, etc.) will be included in Basic and Advanced Search results. Disabling this feature will allow users to search by any location type values attached to the contact.{/ts} diff --git a/tests/phpunit/CRM/Contact/BAO/QueryTest.php b/tests/phpunit/CRM/Contact/BAO/QueryTest.php index 965a3a8f8bef..f6797c1507b2 100644 --- a/tests/phpunit/CRM/Contact/BAO/QueryTest.php +++ b/tests/phpunit/CRM/Contact/BAO/QueryTest.php @@ -152,9 +152,9 @@ public function testSearchProfileHomeCityNoResultsCRM14263() { } /** - * Test searchByPrimaryEmailOnly setting. + * Test searchPrimaryLocTypes setting. */ - public function testSearchByPrimaryEmailOnly() { + public function testSearchPrimaryLocTypes() { $contactID = $this->individualCreate(); $params = array( 'contact_id' => $contactID, @@ -168,7 +168,7 @@ public function testSearchByPrimaryEmailOnly() { $this->callAPISuccess('email', 'create', $params); foreach (array(0, 1) as $searchPrimary) { - Civi::settings()->set('searchPrimaryEmailOnly', $searchPrimary); + Civi::settings()->set('searchPrimaryLocTypes', $searchPrimary); $params = array( 0 => array( From a3fccfc71200bd1cd38abeeeb38711e9cbe7ef0f Mon Sep 17 00:00:00 2001 From: Chris Burgess Date: Fri, 3 Feb 2017 21:15:55 +1300 Subject: [PATCH 3/5] CRM-4287: Change setting name from "searchPrimaryLocTypes" to "searchPrimaryDetailsOnly". Location types are not primaries, contact could have several emails of any location type but only one email (not location type) should be their "primary". --- CRM/Admin/Form/Setting/Search.php | 2 +- CRM/Contact/BAO/Query.php | 2 +- settings/Search.setting.php | 4 ++-- templates/CRM/Admin/Form/Setting/Search.tpl | 6 +++--- tests/phpunit/CRM/Contact/BAO/QueryTest.php | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CRM/Admin/Form/Setting/Search.php b/CRM/Admin/Form/Setting/Search.php index 8435da84269a..5d4a3b2245c5 100644 --- a/CRM/Admin/Form/Setting/Search.php +++ b/CRM/Admin/Form/Setting/Search.php @@ -49,7 +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, - 'searchPrimaryLocTypes' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, + 'searchPrimaryDetailsOnly' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME, ); /** diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index 41c742d4d781..b00ea7993e33 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -2625,7 +2625,7 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima continue; } $searchPrimary = ''; - if (Civi::settings()->get('searchPrimaryLocTypes') || $apiEntity) { + if (Civi::settings()->get('searchPrimaryDetailsOnly') || $apiEntity) { $searchPrimary = " AND {$name}.is_primary = 1"; } switch ($name) { diff --git a/settings/Search.setting.php b/settings/Search.setting.php index d970d08a6698..f64ed7589b6c 100644 --- a/settings/Search.setting.php +++ b/settings/Search.setting.php @@ -197,10 +197,10 @@ 'description' => 'If set, this will be the default profile used for contact search.', 'help_text' => NULL, ), - 'searchPrimaryLocTypes' => array( + 'searchPrimaryDetailsOnly' => array( 'group_name' => 'Search Preferences', 'group' => 'Search Preferences', - 'name' => 'searchPrimaryLocTypes', + 'name' => 'searchPrimaryDetailsOnly', 'type' => 'Boolean', 'quick_form_type' => 'YesNo', 'default' => 1, diff --git a/templates/CRM/Admin/Form/Setting/Search.tpl b/templates/CRM/Admin/Form/Setting/Search.tpl index 5c50ae91838f..d3dd0a29deaf 100644 --- a/templates/CRM/Admin/Form/Setting/Search.tpl +++ b/templates/CRM/Admin/Form/Setting/Search.tpl @@ -37,9 +37,9 @@ {$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.searchPrimaryLocTypes.label} - {$form.searchPrimaryLocTypes.html}
+ + {$form.searchPrimaryDetailsOnly.label} + {$form.searchPrimaryDetailsOnly.html}
{ts}If enabled, only primary location types(email, phone, etc.) will be included in Basic and Advanced Search results. Disabling this feature will allow users to search by any location type values attached to the contact.{/ts} diff --git a/tests/phpunit/CRM/Contact/BAO/QueryTest.php b/tests/phpunit/CRM/Contact/BAO/QueryTest.php index f6797c1507b2..8642b5004138 100644 --- a/tests/phpunit/CRM/Contact/BAO/QueryTest.php +++ b/tests/phpunit/CRM/Contact/BAO/QueryTest.php @@ -152,7 +152,7 @@ public function testSearchProfileHomeCityNoResultsCRM14263() { } /** - * Test searchPrimaryLocTypes setting. + * Test searchPrimaryDetailsOnly setting. */ public function testSearchPrimaryLocTypes() { $contactID = $this->individualCreate(); @@ -168,7 +168,7 @@ public function testSearchPrimaryLocTypes() { $this->callAPISuccess('email', 'create', $params); foreach (array(0, 1) as $searchPrimary) { - Civi::settings()->set('searchPrimaryLocTypes', $searchPrimary); + Civi::settings()->set('searchPrimaryDetailsOnly', $searchPrimary); $params = array( 0 => array( From 0e4873ff86e5277786b28c853f47b7a78f245846 Mon Sep 17 00:00:00 2001 From: Chris Burgess Date: Fri, 3 Feb 2017 21:22:53 +1300 Subject: [PATCH 4/5] CRM-4287. Update template help. --- settings/Search.setting.php | 4 ++-- templates/CRM/Admin/Form/Setting/Search.tpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/settings/Search.setting.php b/settings/Search.setting.php index f64ed7589b6c..6cc84b3f6123 100644 --- a/settings/Search.setting.php +++ b/settings/Search.setting.php @@ -205,10 +205,10 @@ 'quick_form_type' => 'YesNo', 'default' => 1, 'add' => '4.7', - 'title' => 'Search Primary Location Types Only', + 'title' => 'Search Primary Details Only', 'is_domain' => 1, 'is_contact' => 0, - 'description' => 'If enabled, only primary location types(email, phone, etc.) will be included in Basic and Advanced Search results. Disabling this feature will allow users to search by any location type values attached to the contact.', + 'description' => 'If enabled, only primary details (eg contact\'s primary email, phone, etc) will be included in Basic and Advanced Search results. Disabling this feature will allow users to match contacts using any email, phone etc detail.', 'help_text' => NULL, ), ); diff --git a/templates/CRM/Admin/Form/Setting/Search.tpl b/templates/CRM/Admin/Form/Setting/Search.tpl index d3dd0a29deaf..aa5a8766f380 100644 --- a/templates/CRM/Admin/Form/Setting/Search.tpl +++ b/templates/CRM/Admin/Form/Setting/Search.tpl @@ -40,7 +40,7 @@ {$form.searchPrimaryDetailsOnly.label} {$form.searchPrimaryDetailsOnly.html}
- {ts}If enabled, only primary location types(email, phone, etc.) will be included in Basic and Advanced Search results. Disabling this feature will allow users to search by any location type values attached to the contact.{/ts} + {ts}If enabled, only primary details (eg contact's primary email, phone, etc) will be included in Basic and Advanced Search results. Disabling this feature will allow users to match contacts using any email, phone etc detail.{/ts} From 614a507778676e44cc0876f181800b423db33bd8 Mon Sep 17 00:00:00 2001 From: jitendrapurohit Date: Fri, 3 Feb 2017 14:56:53 +0530 Subject: [PATCH 5/5] test fix --- CRM/Contact/BAO/Query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index b00ea7993e33..b7aad4d88b3d 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -2626,7 +2626,7 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima } $searchPrimary = ''; if (Civi::settings()->get('searchPrimaryDetailsOnly') || $apiEntity) { - $searchPrimary = " AND {$name}.is_primary = 1"; + $searchPrimary = "AND {$name}.is_primary = 1"; } switch ($name) { case 'civicrm_address':