From 795dd642194c3712e991897e14d94ee21aedf2da Mon Sep 17 00:00:00 2001 From: Mira Weller Date: Tue, 4 Jun 2024 14:29:50 +0200 Subject: [PATCH] simplify placeholder validation --- src/pretix/base/forms/validators.py | 27 ++++++++++++--------------- src/pretix/control/views/event.py | 18 +++++++++--------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/pretix/base/forms/validators.py b/src/pretix/base/forms/validators.py index e68643b0d..50421e298 100644 --- a/src/pretix/base/forms/validators.py +++ b/src/pretix/base/forms/validators.py @@ -39,7 +39,7 @@ from django.core.validators import BaseValidator from django.utils.translation import gettext_lazy as _ from i18nfield.strings import LazyI18nString -from pretix.helpers.format import SafeFormatter +from pretix.helpers.format import format_map class PlaceholderValidator(BaseValidator): @@ -49,6 +49,12 @@ class PlaceholderValidator(BaseValidator): which are not presented in taken list. """ + error_message = _( + 'There is an error with your placeholder syntax. Please check that the opening "{" and closing "}" curly ' + 'brackets on your placeholders match up. ' + 'Please note: to use literal "{" or "}", you need to double them as "{{" and "}}".' + ) + def __init__(self, limit_value): super().__init__(limit_value) self.limit_value = limit_value @@ -60,23 +66,14 @@ class PlaceholderValidator(BaseValidator): return try: - SafeFormatter(None).parse(value) + format_map(value, {key.strip('{}'): "" for key in self.limit_value}, ignore_missing_keys=False) except ValueError: + raise ValidationError(self.error_message, code='invalid_placeholder_syntax') + except KeyError as e: raise ValidationError( - _('Invalid placeholder syntax: You used a different number of "{" than of "}".'), - code='invalid_placeholder_syntax', - ) - - data_placeholders = list(re.findall(r'({[^}]*})', value, re.X)) - invalid_placeholders = [] - for placeholder in data_placeholders: - if placeholder not in self.limit_value: - invalid_placeholders.append(placeholder) - if invalid_placeholders: - raise ValidationError( - _('Invalid placeholder(s): %(value)s'), + _('Invalid placeholder: {%(value)s}'), code='invalid_placeholders', - params={'value': ", ".join(invalid_placeholders,)}) + params={'value': e.args[0]}) def clean(self, x): return x diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index cffd876b1..3bdb03257 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -73,6 +73,7 @@ from i18nfield.utils import I18nJSONEncoder from pretix.base.channels import get_all_sales_channels from pretix.base.email import get_available_placeholders +from pretix.base.forms import PlaceholderValidator from pretix.base.models import Event, LogEntry, Order, TaxRule, Voucher from pretix.base.models.event import EventMetaValue from pretix.base.services import tickets @@ -713,11 +714,6 @@ class MailSettingsSetup(EventPermissionRequiredMixin, MailSettingsSetupView): class MailSettingsPreview(EventPermissionRequiredMixin, View): permission = 'can_change_event_settings' - # return the origin text if key is missing in dict - class SafeDict(dict): - def __missing__(self, key): - return '{' + key + '}' - # create index-language mapping @cached_property def supported_locale(self): @@ -742,7 +738,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View): _('This value will be replaced based on dynamic parameters.'), s ) - return self.SafeDict(ctx) + return ctx def post(self, request, *args, **kwargs): preview_item = request.POST.get('item', '') @@ -760,13 +756,17 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View): with language(self.supported_locale[idx], self.request.event.settings.region): try: if k.startswith('mail_subject_'): - msgs[self.supported_locale[idx]] = format_map(bleach.clean(v), self.placeholders(preview_item)) + msgs[self.supported_locale[idx]] = format_map(bleach.clean(v), self.placeholders(preview_item), ignore_missing_keys=False) else: msgs[self.supported_locale[idx]] = markdown_compile_email( - format_map(v, self.placeholders(preview_item)) + format_map(v, self.placeholders(preview_item), ignore_missing_keys=False) ) except ValueError: - msgs[self.supported_locale[idx]] = _('Invalid placeholder syntax: You used a different number of "{" than of "}".') + msgs[self.supported_locale[idx]] = '
{}
'.format( + PlaceholderValidator.error_message) + except KeyError as e: + msgs[self.supported_locale[idx]] = '
{}
'.format( + _('Invalid placeholder: {%(value)s}') % {'value': e.args[0]}) return JsonResponse({ 'item': preview_item,