Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM:4287 - add searchPrimaryDetailsOnly setting #9772

Merged
merged 5 commits into from
Mar 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CRM/Admin/Form/Setting/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
'searchPrimaryDetailsOnly' => CRM_Core_BAO_Setting::SEARCH_PREFERENCES_NAME,
);

/**
Expand Down
27 changes: 15 additions & 12 deletions CRM/Contact/BAO/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I last looked at this apiEntity seemed to duplicate $this->_mode.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually $this->_mode contain the constant values specified in https://github.com/jitendrapurohit/civicrm-core/blob/master/CRM/Contact/BAO/Query.php#L47 and apiEntity is assigned with string entity values e.g. Contact, Participant etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for the record, I still don't understand how that isn't just duplicating mode in a different format (you don't need to respond to this - it has been merged & it is not a 'live' concern)

$this->_simpleFromClause = self::fromClause($this->_whereTables, NULL, NULL, $this->_primaryLocation, $this->_mode);

$this->openedSearchPanes(TRUE);
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -2623,27 +2624,29 @@ public static function fromClause(&$tables, $inner = NULL, $right = NULL, $prima
}
continue;
}
$searchPrimary = '';
if (Civi::settings()->get('searchPrimaryDetailsOnly') || $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':
$from .= " $side JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id AND civicrm_email.is_primary = 1) ";
$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':
Expand All @@ -2653,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':
Expand Down
14 changes: 14 additions & 0 deletions settings/Search.setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,18 @@
'description' => 'If set, this will be the default profile used for contact search.',
'help_text' => NULL,
),
'searchPrimaryDetailsOnly' => array(
'group_name' => 'Search Preferences',
'group' => 'Search Preferences',
'name' => 'searchPrimaryDetailsOnly',
'type' => 'Boolean',
'quick_form_type' => 'YesNo',
'default' => 1,
'add' => '4.7',
'title' => 'Search Primary Details Only',
'is_domain' => 1,
'is_contact' => 0,
'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,
),
);
6 changes: 6 additions & 0 deletions templates/CRM/Admin/Form/Setting/Search.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
<td>{$form.includeEmailInName.html}<br />
<span class="description">{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}</span></td>
</tr>
<tr class="crm-search-setting-form-block-searchPrimaryDetailsOnly">
<td class="label">{$form.searchPrimaryDetailsOnly.label}</td>
<td>{$form.searchPrimaryDetailsOnly.html}<br />
<span class="description">{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}</span>
</td>
</tr>
<tr class="crm-search-setting-form-block-includeNickNameInName">
<td class="label">{$form.includeNickNameInName.label}</td>
<td>{$form.includeNickNameInName.html}<br />
Expand Down
56 changes: 56 additions & 0 deletions tests/phpunit/CRM/Contact/BAO/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,62 @@ public function testSearchProfileHomeCityNoResultsCRM14263() {
}
}

/**
* Test searchPrimaryDetailsOnly setting.
*/
public function testSearchPrimaryLocTypes() {
$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('searchPrimaryDetailsOnly', $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
Expand Down