+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2016 |
+ | Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
throw new \Civi\API\Exception\UnauthorizedException('Permission denied to modify contact record');
}
- $dupeCheck = CRM_Utils_Array::value('dupe_check', $params, FALSE);
- $values = _civicrm_api3_contact_check_params($params, $dupeCheck);
+ if (!empty($params['dupe_check'])) {
+ $ids = CRM_Contact_BAO_Contact::getDuplicateContacts($params, $params['contact_type'], 'Unsupervised', array(), $params['check_permission']);
+ if (count($ids) > 0) {
+ throw new API_Exception("Found matching contacts: " . implode(',', $ids), "duplicate", array("ids" => $ids));
+ }
+ }
+
+ $values = _civicrm_api3_contact_check_params($params);
if ($values) {
return $values;
}
unset($params['filter.group_id']);
$options['input_params']['group'] = $groups;
}
+ if (isset($params['group'])) {
+ $groups = $params['group'];
+ $allGroups = CRM_Core_PseudoConstant::group();
+ if (is_array($groups) && in_array(key($groups), CRM_Core_DAO::acceptedSQLOperators(), TRUE)) {
+ // Get the groups array.
+ $groupsArray = $groups[key($groups)];
+ foreach ($groupsArray as &$group) {
+ if (!is_numeric($group) && array_search($group, $allGroups)) {
+ $group = array_search($group, $allGroups);
+ }
+ }
+ // Now reset the $groups array with the ids not the titles.
+ $groups[key($groups)] = $groupsArray;
+ }
+ // handle format like 'group' => array('title1', 'title2').
+ elseif (is_array($groups)) {
+ foreach ($groups as $k => &$group) {
+ if (!is_numeric($group) && array_search($group, $allGroups)) {
+ $group = array_search($group, $allGroups);
+ }
+ if (!is_numeric($k) && array_search($k, $allGroups)) {
+ unset($groups[$k]);
+ $groups[array_search($k, $allGroups)] = $group;
+ }
+ }
+ }
+ elseif (!is_numeric($groups) && array_search($groups, $allGroups)) {
+ $groups = array_search($groups, $allGroups);
+ }
+ $params['group'] = $groups;
+ }
}
/**
* This function is on it's way out.
*
* @param array $params
- * @param bool $dupeCheck
*
* @return null
* @throws API_Exception
* @throws CiviCRM_API3_Exception
*/
-function _civicrm_api3_contact_check_params(&$params, $dupeCheck) {
+function _civicrm_api3_contact_check_params(&$params) {
switch (strtolower(CRM_Utils_Array::value('contact_type', $params))) {
case 'household':
}
}
- if ($dupeCheck) {
- // check for record already existing
- $dedupeParams = CRM_Dedupe_Finder::formatParams($params, $params['contact_type']);
-
- // CRM-6431
- // setting 'check_permission' here means that the dedupe checking will be carried out even if the
- // person does not have permission to carry out de-dupes
- // this is similar to the front end form
- if (isset($params['check_permission'])) {
- $dedupeParams['check_permission'] = $params['check_permission'];
- }
-
- $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['contact_type'], 'Unsupervised', array());
-
- if (count($ids) > 0) {
- throw new API_Exception("Found matching contacts: " . implode(',', $ids), "duplicate", array("ids" => $ids));
- }
- }
-
// The BAO no longer supports the legacy param "current_employer" so here is a shim for api backward-compatability
if (!empty($params['current_employer'])) {
$organizationParams = array(
'organization_name' => $params['current_employer'],
);
- $dedupParams = CRM_Dedupe_Finder::formatParams($organizationParams, 'Organization');
-
- $dedupParams['check_permission'] = FALSE;
- $dupeIds = CRM_Dedupe_Finder::dupesByParams($dedupParams, 'Organization', 'Supervised');
+ $dupeIds = CRM_Contact_BAO_Contact::getDuplicateContacts($organizationParams, 'Organization', 'Supervised', array(), FALSE);
// check for mismatch employer name and id
if (!empty($params['employer_id']) && !in_array($params['employer_id'], $dupeIds)) {
if ($aclWhere) {
$where .= " AND $aclWhere ";
}
+ $isPrependWildcard = \Civi::settings()->get('includeWildCardInName');
if (!empty($params['org'])) {
$where .= " AND contact_type = \"Organization\"";
(int) $params['employee_id'],
'employer_id'
)) {
- if ($config->includeWildCardInName) {
+ if ($isPrependWildcard) {
$strSearch = "%$name%";
}
else {
$rel = CRM_Utils_Type::escape($relation[2], 'String');
}
- if ($config->includeWildCardInName) {
+ if ($isPrependWildcard) {
$strSearch = "%$name%";
}
else {
//CRM-10687
if (!empty($params['field_name']) && !empty($params['table_name'])) {
$whereClause = " WHERE ( $table_name.$field_name LIKE '$strSearch') {$where}";
- $exactWhereClause = " WHERE ( $table_name.$field_name = '$name') {$where}";
// Search by id should be exact
if ($field_name == 'id' || $field_name == 'external_identifier') {
- $whereClause = $exactWhereClause;
+ $whereClause = " WHERE ( $table_name.$field_name = '$name') {$where}";
}
}
else {
$whereClause = " WHERE ( sort_name LIKE '$strSearch' $includeNickName ) {$where} ";
- $exactWhereClause = " WHERE ( sort_name LIKE '$name' $exactIncludeNickName ) {$where} ";
if ($config->includeEmailInName) {
if (!in_array('email', $list)) {
$includeEmailFrom = "LEFT JOIN civicrm_email eml ON ( cc.id = eml.contact_id AND eml.is_primary = 1 )";
INNER JOIN civicrm_uf_match um ON (um.contact_id=cc.id)
";
}
-
- $orderByInner = $orderByOuter = "ORDER BY exactFirst";
- if ($config->includeOrderByClause) {
- $orderByInner = "ORDER BY exactFirst, sort_name";
- $orderByOuter .= ", sort_name";
- }
+ $orderBy = _civicrm_api3_quicksearch_get_order_by($name, $isPrependWildcard, $field_name);
//CRM-5954
$query = "
{$aclFrom}
{$additionalFrom}
{$whereClause}
- {$orderByInner}
+ {$orderBy}
LIMIT 0, {$limit} )
";
{$aclFrom}
{$additionalFrom} {$includeEmailFrom}
{$emailWhere} AND cc.is_deleted = 0 " . ($aclWhere ? " AND $aclWhere " : '') . "
- {$orderByInner}
+ {$orderBy}
LIMIT 0, {$limit}
)
";
}
$query .= ") t
- {$orderByOuter}
+ {$orderBy}
LIMIT 0, {$limit}
";
return civicrm_api3_create_success($contactList, $params, 'Contact', 'getquick');
}
+/**
+ * Get the order by string for the quicksearch query.
+ *
+ * Get the order by string. The string might be
+ * - sort name if there is no search value provided and the site is configured
+ * to search by sort name
+ * - empty if there is no search value provided and the site is not configured
+ * to search by sort name
+ * - exactFirst and then sort name if a search value is provided and the site is configured
+ * to search by sort name
+ * - exactFirst if a search value is provided and the site is not configured
+ * to search by sort name
+ *
+ * exactFirst means 'yes if the search value exactly matches the searched field. else no'.
+ * It is intended to prioritise exact matches for the entered string so on a first name search
+ * for 'kath' contacts with a first name of exactly Kath rise to the top.
+ *
+ * On short strings it is expensive. Per CRM-19547 there is still an open question
+ * as to whether we should only do exactMatch on a minimum length or on certain fields.
+ *
+ * However, we have mitigated this somewhat by not doing an exact match search on
+ * empty strings, non-wildcard sort-name searches and email searches where there is
+ * no @ after the first character.
+ *
+ * For the user it is further mitigated by the fact they just don't know the
+ * slower queries are firing. If they type 'smit' slowly enough 4 queries will trigger
+ * but if the first 3 are slow the first result they see may be off the 4th query.
+ *
+ * @param string $name
+ * @param bool $isPrependWildcard
+ * @param string $field_name
+ *
+ * @return string
+ */
+function _civicrm_api3_quicksearch_get_order_by($name, $isPrependWildcard, $field_name) {
+ $skipExactMatch = ($name === '%');
+ if ($field_name === 'email' && !strpos('@', $name)) {
+ $skipExactMatch = TRUE;
+ }
+
+ if (!\Civi::settings()->get('includeOrderByClause')) {
+ return $skipExactMatch ? '' : "ORDER BY exactFirst";
+ }
+ if ($skipExactMatch || (!$isPrependWildcard && $field_name === 'sort_name')) {
+ // If there is no wildcard then sorting by exactFirst would have the same
+ // effect as just a sort_name search, but slower.
+ return "ORDER BY sort_name";
+ }
+
+ return "ORDER BY exactFirst, sort_name";
+}
+
/**
* Declare deprecated api functions.
*
* -int main_id: main contact id with whom merge has to happen
* -int other_id: duplicate contact which would be deleted after merge operation
* -string mode: "safe" skips the merge if there are no conflicts. Does a force merge otherwise.
- * -boolean auto_flip: whether to let api decide which contact to retain and which to delete.
*
* @return array
* API Result Array
- * @throws CiviCRM_API3_Exception
+ * @throws API_Exception
*/
function civicrm_api3_contact_merge($params) {
if (($result = CRM_Dedupe_Merger::merge(array(
'srcID' => $params['to_remove_id'],
'dstID' => $params['to_keep_id'],
),
- ), array(), $params['mode'], $params['auto_flip'])) != FALSE) {
+ ), array(), $params['mode'])) != FALSE) {
return civicrm_api3_create_success($result, $params);
}
- throw new CiviCRM_API3_Exception('Merge failed');
+ throw new API_Exception('Merge failed');
}
/**
'type' => CRM_Utils_Type::T_INT,
'api.aliases' => array('other_id'),
);
- $params['auto_flip'] = array(
- 'title' => 'Swap destination and source to retain lowest id?',
- 'api.default' => TRUE,
- );
$params['mode'] = array(
// @todo need more detail on what this means.
'title' => 'Dedupe mode',
* API formatted array
*/
function civicrm_api3_contact_duplicatecheck($params) {
- $dedupeParams = CRM_Dedupe_Finder::formatParams($params['match'], $params['match']['contact_type']);
-
- // CRM-6431
- // setting 'check_permission' here means that the dedupe checking will be carried out even if the
- // person does not have permission to carry out de-dupes
- // this is similar to the front end form
- if (isset($params['check_permission'])) {
- $dedupeParams['check_permission'] = $params['check_permission'];
- }
-
- $dupes = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $params['match']['contact_type'], 'Unsupervised', array(), CRM_Utils_Array::value('dedupe_rule_id', $params));
+ $dupes = CRM_Contact_BAO_Contact::getDuplicateContacts(
+ $params['match'],
+ $params['match']['contact_type'],
+ 'Unsupervised',
+ array(),
+ CRM_Utils_Array::value('check_permissions', $params),
+ CRM_Utils_Array::value('dedupe_rule_id', $params)
+ );
$values = empty($dupes) ? array() : array_fill_keys($dupes, array());
return civicrm_api3_create_success($values, $params, 'Contact', 'duplicatecheck');
}