affiner la détection de numéro de téléphone pour la recherche fts (#75594) #177

Merged
fpeters merged 2 commits from wip/75594-sql-single-fts into main 2023-03-21 07:54:40 +01:00
2 changed files with 12 additions and 23 deletions

View File

@ -4442,7 +4442,7 @@ def test_fts_phone(pub):
assert formdef.data_class().count([FtsMatch('+33(0)123456789 bar')]) == 0
assert formdef.data_class().count([FtsMatch('foo +33(0)123456789')]) == 1
assert formdef.data_class().count([FtsMatch('bar +33(0)123456789')]) == 0
assert formdef.data_class().count([FtsMatch('123456789')]) == 2
assert formdef.data_class().count([FtsMatch('123456789')]) == 1
formdata.data = {'1': '+32 2 345 67 89', '2': 'foo'}
formdata.store()

View File

@ -440,38 +440,27 @@ class FtsMatch(Criteria):
self.attribute = 'fts'
self.value = self.get_fts_value(value)
if extra_normalize:
phone_match = re.match(r'.*?(?P<phone>\b\+?[-\(\)\d\.\s/]{6,20}\b)', self.value)
if phone_match:
phone_match = re.match(
r'''.*?(?P<phone> # a phone number
((\+[1-9])|(\b0)) # starting with an international prefix, or 0
[-\(\)\d\.\s/]{6,20} # then a bunch of numbers/symbols
\b) # till the end of the "word"''',
self.value,
re.X,
)
if phone_match and not re.match(r'^\d+-\d+$', phone_match.group('phone').strip()):
# if it looks like a phone number, normalize it to its
# "international/E164" format to match what's stored in the
# database.
phone_value = misc.normalize_phone_number_for_fts(phone_match.group('phone').strip())
self.value = [self.value, self.value.replace(phone_match.group('phone').strip(), phone_value)]
self.value = self.value.replace(phone_match.group('phone').strip(), phone_value)
@classmethod
def get_fts_value(cls, value):
return unidecode.unidecode(value)
def as_sql(self):
if isinstance(self.value, list):
parts = []
for value in self.value:
parts.append('(%s)' % self.as_sql_part(value))
return '(%s)' % ' or '.join(parts)
else:
return self.as_sql_part(self.value)
def as_sql_part(self, value):
return 'fts @@ plainto_tsquery(%%(%s)s)' % self.value_to_identifier(value)
def value_to_identifier(self, value):
return 'c%s' % id(value)
def as_sql_param(self):
if isinstance(self.value, list):
return {self.value_to_identifier(value): value for value in self.value}
else:
return {self.value_to_identifier(self.value): self.value}
return 'fts @@ plainto_tsquery(%%(c%s)s)' % id(self.value)
class ElementEqual(Criteria):