aggregate Etemplate\Widget\Url::ajax_contact() requests and search for all of them in a single AJAX request and SQL query

This commit is contained in:
ralf 2023-07-25 18:18:16 +02:00
parent 2a5d0062dd
commit a89b69528e
2 changed files with 64 additions and 20 deletions

View File

@ -117,17 +117,42 @@ export class Et2EmailTag extends Et2Tag
this.removeEventListener("mouseleave", this.handleMouseLeave); this.removeEventListener("mouseleave", this.handleMouseLeave);
} }
static contact_request : Promise<any>;
static contact_requests : { [key: string]: Array<Function>; } = {};
public checkContact(email : string) : Promise<boolean | ContactInfo> public checkContact(email : string) : Promise<boolean | ContactInfo>
{ {
if(typeof Et2EmailTag.email_cache[email] !== "undefined") if(typeof Et2EmailTag.email_cache[email] !== "undefined")
{ {
return Promise.resolve(Et2EmailTag.email_cache[email]); return Promise.resolve(Et2EmailTag.email_cache[email]);
} }
return this.egw().jsonq('EGroupware\\Api\\Etemplate\\Widget\\Url::ajax_contact', [email]).then( if (!Et2EmailTag.contact_request)
(result) =>
{ {
Et2EmailTag.email_cache[email] = result; Et2EmailTag.contact_request = this.egw().jsonq('EGroupware\\Api\\Etemplate\\Widget\\Url::ajax_contact', [[]], null, null,
return result; (parameters) => {
for(const email in Et2EmailTag.contact_requests)
{
parameters[0].push(email);
}
}).then((result) =>
{
for(const email in Et2EmailTag.contact_requests)
{
Et2EmailTag.email_cache[email] = result[email];
Et2EmailTag.contact_requests[email].forEach((resolve) => {
resolve(result[email]);
});
}
Et2EmailTag.contact_request = null;
Et2EmailTag.contact_requests = {};
});
}
if (typeof Et2EmailTag.contact_requests[email] === 'undefined')
{
Et2EmailTag.contact_requests[email] = [];
}
return new Promise(resolve => {
Et2EmailTag.contact_requests[email].push(resolve);
}); });
} }

View File

@ -16,6 +16,7 @@
namespace EGroupware\Api\Etemplate\Widget; namespace EGroupware\Api\Etemplate\Widget;
use EGroupware\Api\Etemplate; use EGroupware\Api\Etemplate;
use EGroupware\Api;
/** /**
* eTemplate URL widget handles URLs, emails & phone numbers * eTemplate URL widget handles URLs, emails & phone numbers
@ -152,31 +153,49 @@ class Url extends Etemplate\Widget
/** /**
* Handle ajax searches for existing contact based on email * Handle ajax searches for existing contact based on email
* *
* @return Array|boolean Contact data of first match, or false if contact does not exist * @param string|string[] $_email
* @return Array|boolean Contact data of first match, or false if contact does not exist or
* for string[] array/object with email as key and the above as value
*/ */
public static function ajax_contact($_email) public static function ajax_contact($_email)
{ {
$email = \EGroupware\Api\Mail::stripRFC822Addresses(array($_email)); $emails = Api\Mail::stripRFC822Addresses((array)$_email);
$response = \EGroupware\Api\Json\Response::get(); $response = Api\Json\Response::get();
$result = $GLOBALS['egw']->contacts->search( $result = $GLOBALS['egw']->contacts->search(
array('contact_email' => $email[0], 'contact_email_home' => $email[0]), array('contact_email' => $emails, 'contact_email_home' => $emails),
array('contact_id', 'email', 'email_home', 'n_fn'), array('contact_id', 'email', 'email_home', 'n_fn'),
'', '', '%', false, 'OR', false '', '', '%', false, 'OR', false
); );
// iterate through the possibilities and find the best match to what was entered // iterate through the possibilities and find the best match to what was entered
$best_match = null; $best_matches = [];
$best_match_score = -1; $best_scores = [];
foreach($emails as $key => $email)
{
$len_email = strlen($email);
$query = strtolower(((array)$_email)[$key]);
foreach($result as $possibility) foreach($result as $possibility)
{ {
$score = max(similar_text(strtolower($_email), strtolower($possibility['n_fn'] . " " . $possibility['email'])), if (!strcasecmp($email, (substr($possibility['email'], -1) === '>' ?
similar_text(strtolower($_email), strtolower($possibility['n_fn'] . " " . $possibility['email_home'])) substr($possibility['email'], -$len_email-1, -1) : $possibility['email'])) ||
); !strcasecmp($email, (substr($possibility['email_home'], -1) === '>' ?
if($score > $best_match_score) substr($possibility['email_home'], -$len_email-1, -1) : $possibility['email_home'])))
{ {
$best_match_score = $score; $score = max(similar_text($query, strtolower($possibility['n_fn'] . " " . $possibility['email'])),
$best_match = $possibility; similar_text($query, strtolower($possibility['n_fn'] . " " . $possibility['email_home']))
);
if (!isset($best_scores[$key]) || $score > $best_scores[$key])
{
$best_scores[$key] = $score;
$best_matches[$key] = $possibility;
} }
} }
$response->data($result ? $best_match : false); }
}
$result = [];
foreach((array)$_email as $key => $value)
{
$result[$value] = $best_matches[$key] ?? false;
}
$response->data(is_array($_email) ? $result : array_shift($result));
} }
} }