From 12addea3c1b9731ac73a320afd566739797d8cb9 Mon Sep 17 00:00:00 2001 From: Dominic Tubach Date: Thu, 27 Feb 2025 13:18:38 +0100 Subject: [PATCH 1/2] Use APIv4 for contact lookup --- api/v3/BankingLookup.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/api/v3/BankingLookup.php b/api/v3/BankingLookup.php index 5b529c77..e3ee6181 100644 --- a/api/v3/BankingLookup.php +++ b/api/v3/BankingLookup.php @@ -21,6 +21,7 @@ * @package CiviBanking Extension */ +use Civi\Api4\Contact; /** * Will provide a name based lookup for contacts. It is designed to take care of @@ -292,25 +293,24 @@ function _civicrm_api3_banking_lookup_contactbyname_sql($name_mutations, $params /** * find some contacts via API */ -function _civicrm_api3_banking_lookup_contactbyname_api($name_mutations, $params) { - $contacts_found = array(); - // query quicksearch for each combination +function _civicrm_api3_banking_lookup_contactbyname_api($name_mutations, $params): array { + $contacts_found = []; + // query Contact.autocomplete for each combination foreach ($name_mutations as $name_mutation) { - $result = civicrm_api3('Contact', 'getquick', array('name' => $name_mutation)); - foreach ($result['values'] as $contact) { + $result = Contact::autocomplete() + ->setInput($name_mutation) + ->execute(); + /** @phpstan-var array{id: int, label: string, icon: string, description: list} $contact_autocomplete */ + foreach ($result as $contact_autocomplete) { + $contact_id = $contact_autocomplete['id']; // get the current maximum similarity... - if (isset($contacts_found[$contact['id']])) { - $probability = $contacts_found[$contact['id']]; - } else { - $probability = 0.0; - } + $probability = $contacts_found[$contact_id] ?? 0.0; // now, we'll have to find the maximum similarity with any of the name mutations - $compare_name = strtolower($contact['sort_name']); + $compare_name = strtolower($contact_autocomplete['label']); foreach ($name_mutations as $name_mutation) { $new_probability = 0.0; similar_text(strtolower($name_mutation), $compare_name, $new_probability); - //error_log("Compare '$name_mutation' to '".$contact['sort_name']."' => $new_probability"); $new_probability /= 100.0; if ($new_probability > $probability) { // square value for better distribution, multiply by 0.999 to avoid 100% match based on name @@ -318,7 +318,7 @@ function _civicrm_api3_banking_lookup_contactbyname_api($name_mutations, $params } } - $contacts_found[$contact['id']] = $probability; + $contacts_found[$contact_id] = $probability; } } From 12fd5faa124e8567fa7d5c14e8aea2f492acea7b Mon Sep 17 00:00:00 2001 From: Dominic Tubach Date: Fri, 28 Feb 2025 12:42:09 +0100 Subject: [PATCH 2/2] Improve contact probability calculation --- api/v3/BankingLookup.php | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/api/v3/BankingLookup.php b/api/v3/BankingLookup.php index e3ee6181..f7ba6c40 100644 --- a/api/v3/BankingLookup.php +++ b/api/v3/BankingLookup.php @@ -294,7 +294,8 @@ function _civicrm_api3_banking_lookup_contactbyname_sql($name_mutations, $params * find some contacts via API */ function _civicrm_api3_banking_lookup_contactbyname_api($name_mutations, $params): array { - $contacts_found = []; + $contacts_probability = []; + $occurrence_count = []; // query Contact.autocomplete for each combination foreach ($name_mutations as $name_mutation) { $result = Contact::autocomplete() @@ -303,26 +304,34 @@ function _civicrm_api3_banking_lookup_contactbyname_api($name_mutations, $params /** @phpstan-var array{id: int, label: string, icon: string, description: list} $contact_autocomplete */ foreach ($result as $contact_autocomplete) { $contact_id = $contact_autocomplete['id']; + $occurrence_count[$contact_id] = ($occurrence_count[$contact_id] ?? 0) + 1; // get the current maximum similarity... - $probability = $contacts_found[$contact_id] ?? 0.0; + $probability = $contacts_probability[$contact_id] ?? 0.0; // now, we'll have to find the maximum similarity with any of the name mutations - $compare_name = strtolower($contact_autocomplete['label']); + $contact_name = strtolower($contact_autocomplete['label']); foreach ($name_mutations as $name_mutation) { $new_probability = 0.0; - similar_text(strtolower($name_mutation), $compare_name, $new_probability); + similar_text(strtolower($name_mutation), $contact_name, $new_probability); $new_probability /= 100.0; + // square value for better distribution, multiply by 0.999 to avoid 100% match based on name + $new_probability = $new_probability * $new_probability * 0.999; if ($new_probability > $probability) { - // square value for better distribution, multiply by 0.999 to avoid 100% match based on name - $probability = $new_probability * $new_probability * 0.999; + $probability = $new_probability; } } + $contacts_probability[$contact_id] = $probability; + } + } - $contacts_found[$contact_id] = $probability; + if ([] !== $contacts_probability) { + $max_occurrence = max($occurrence_count); + foreach ($contacts_probability as $contact_id => $probability) { + $contacts_probability[$contact_id] = $probability * $occurrence_count[$contact_id] / $max_occurrence; } } - return $contacts_found; + return $contacts_probability; } /**