fulltext search in email address lookup

This commit is contained in:
Yuri Kuznetsov
2022-04-12 12:49:51 +03:00
parent 86f67bd315
commit 7e5a7546f2
3 changed files with 75 additions and 37 deletions
@@ -41,6 +41,8 @@ use Espo\Core\{
class EmailAddress extends RecordBase
{
private const ADDRESS_MAX_SIZE = 50;
/**
* @return array<int,array<string,mixed>>
*/
@@ -62,8 +64,8 @@ class EmailAddress extends RecordBase
$maxSize = intval($request->getQueryParam('maxSize'));
if (empty($maxSize) || $maxSize > 50) {
$maxSize = $this->config->get('recordsPerPage', 20);
if (!$maxSize || $maxSize > self::ADDRESS_MAX_SIZE) {
$maxSize = (int) $this->config->get('recordsPerPage');
}
$onlyActual = $request->getQueryParam('onlyActual') === 'true';
@@ -436,6 +436,6 @@
"collection": {
"orderBy": "userName",
"order": "asc",
"textFilterFields": ["name", "userName"]
"textFilterFields": ["name", "userName", "emailAddress"]
}
}
+70 -34
View File
@@ -34,12 +34,16 @@ use Espo\Entities\EmailAddress as EmailAddressEntity;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
use Espo\Core\Select\Text\MetadataProvider as TextMetadataProvider;
/**
* @extends Record<\Espo\Entities\EmailAddress>
*/
class EmailAddress extends Record
{
const ERASED_PREFIX = 'ERASED:';
private const ERASED_PREFIX = 'ERASED:';
private ?TextMetadataProvider $textMetadataProvider = null;
/**
* @param array<int,array<string,mixed>> $result
@@ -52,35 +56,56 @@ class EmailAddress extends Record
bool $onlyActual = false
): void {
$whereClause = [
'OR' => [
[
'name*' => $filter . '%',
],
[
'emailAddress*' => $filter . '%',
],
],
[
'emailAddress!=' => null,
],
];
$textFilter = null;
$whereClause = [];
$builder = $this->selectBuilderFactory
$byEmailAddress = false;
if (strpos($filter, '@') !== false) {
$byEmailAddress = true;
}
if (
!$byEmailAddress &&
mb_strlen($filter) < (int) $this->config->get('fullTextSearchMinLength') &&
$this->hasFullTextSearch($entityType)
) {
$byEmailAddress = true;
}
if ($byEmailAddress) {
$whereClause = [
'emailAddress*' => $filter . '%',
];
}
else {
$textFilter = $filter;
}
$selectBuilder = $this->selectBuilderFactory
->create()
->from($entityType)
->withAccessControlFilter()
->withAccessControlFilter();
if ($textFilter) {
$selectBuilder->withTextFilter($textFilter);
}
$builder = $selectBuilder
->buildQueryBuilder()
->where($whereClause)
->order('name')
->limit(0, $limit);
$handleMethodName = 'handleQueryBuilder' . $entityType;
if (method_exists($this, $handleMethodName)) {
$this->$handleMethodName($filter, $builder);
if ($textFilter) {
$builder
->join('emailAddresses', 'emailAddressesJoin')
->distinct();
}
if ($entityType === 'User') {
$this->handleQueryBuilderUser($filter, $builder);
}
$select = ['id', 'emailAddress', 'name'];
@@ -107,24 +132,26 @@ class EmailAddress extends Record
$skipPrimaryEmailAddress = false;
if ($emailAddress) {
if (strpos($emailAddress, self::ERASED_PREFIX) === 0) {
if (!$emailAddress) {
continue;
}
if (strpos($emailAddress, self::ERASED_PREFIX) === 0) {
$skipPrimaryEmailAddress = true;
}
if ($onlyActual) {
if ($entity->get('emailAddressIsOptedOut')) {
$skipPrimaryEmailAddress = true;
}
if ($onlyActual) {
if ($entity->get('emailAddressIsOptedOut')) {
$skipPrimaryEmailAddress = true;
foreach ($emailAddressData as $item) {
if ($emailAddress !== $item->emailAddress) {
continue;
}
foreach ($emailAddressData as $item) {
if ($emailAddress !== $item->emailAddress) {
continue;
}
if (!empty($item->invalid)) {
$skipPrimaryEmailAddress = true;
}
if (!empty($item->invalid)) {
$skipPrimaryEmailAddress = true;
}
}
}
@@ -167,7 +194,7 @@ class EmailAddress extends Record
}
}
protected function handleQueryBuilderUser(string $filter, QueryBuilder $queryBuilder): void
private function handleQueryBuilderUser(string $filter, QueryBuilder $queryBuilder): void
{
if ($this->acl->get('portalPermission') === 'no') {
$queryBuilder->where([
@@ -298,4 +325,13 @@ class EmailAddress extends Record
/** @var Repository */
return $this->entityManager->getRepository(EmailAddressEntity::ENTITY_TYPE);
}
private function hasFullTextSearch(string $entityType): bool
{
if ($this->textMetadataProvider === null) {
$this->textMetadataProvider = $this->injectableFactory->create(TextMetadataProvider::class);
}
return $this->textMetadataProvider->hasFullTextSearch($entityType);
}
}