|
1 | 1 | import hashlib |
2 | 2 |
|
| 3 | +from django import forms |
3 | 4 | from django.core.exceptions import ImproperlyConfigured |
4 | 5 | from django.core.mail import mail_admins, send_mail |
| 6 | +from django.core.validators import EmailValidator |
| 7 | +from django.template import TemplateDoesNotExist |
5 | 8 | from django.template.loader import render_to_string |
6 | 9 | from django.utils.html import strip_tags |
7 | 10 | from django.utils.translation import gettext_lazy as _ |
| 11 | +from entangled.forms import EntangledModelFormMixin |
8 | 12 |
|
| 13 | +from . import models |
9 | 14 | from .entry_model import FormEntry |
10 | | -from .helpers import get_option |
| 15 | +from .helpers import get_option, insert_fields |
| 16 | +from .settings import MAIL_TEMPLATE_SETS |
11 | 17 |
|
12 | 18 | _action_registry = {} |
13 | 19 |
|
@@ -38,16 +44,63 @@ def register(action_class): |
38 | 44 | return action_class |
39 | 45 |
|
40 | 46 |
|
| 47 | +def unregister(action_class): |
| 48 | + hash = hashlib.sha1(action_class.__name__.encode("utf-8")).hexdigest() |
| 49 | + if hash in _action_registry: |
| 50 | + del _action_registry[hash] |
| 51 | + return action_class |
| 52 | + |
| 53 | + |
41 | 54 | def get_action_class(action): |
42 | 55 | return _action_registry.get(action, None) |
43 | 56 |
|
44 | 57 |
|
45 | | -class FormAction: |
| 58 | +class ActionMixin: |
| 59 | + """Adds action form elements to Form plugin admin""" |
| 60 | + def get_form(self, request, *args, **kwargs): |
| 61 | + """Creates new form class based adding the actions as mixins""" |
| 62 | + return type( |
| 63 | + "FormActionAdminForm", |
| 64 | + (self.form, *_action_registry.values()), |
| 65 | + {} |
| 66 | + ) |
| 67 | + |
| 68 | + def get_fieldsets(self, request, obj=None): |
| 69 | + fieldsets = super().get_fieldsets(request, obj) |
| 70 | + for action in _action_registry.values(): |
| 71 | + new_fields = list(action.declared_fields.keys()) |
| 72 | + if new_fields: |
| 73 | + hash = hashlib.sha1(action.__name__.encode("utf-8")).hexdigest() |
| 74 | + fieldsets = insert_fields( |
| 75 | + fieldsets, |
| 76 | + new_fields, |
| 77 | + block=None, |
| 78 | + position=-1, |
| 79 | + blockname=action.verbose_name, |
| 80 | + blockattrs=dict(classes=(hash, 'action-hide')), |
| 81 | + ) |
| 82 | + return fieldsets |
| 83 | + |
| 84 | + |
| 85 | +class FormAction(EntangledModelFormMixin): |
| 86 | + class Meta: |
| 87 | + entangled_fields = {"action_parameters": []} |
| 88 | + model = models.Form |
| 89 | + exclude = () |
| 90 | + |
| 91 | + class Media: |
| 92 | + js = ("djangocms_form_builder/js/actions_form.js",) |
| 93 | + css = {"all": ("djangocms_form_builder/css/actions_form.css",)} |
| 94 | + |
46 | 95 | verbose_name = None |
47 | 96 |
|
48 | 97 | def execute(self, form, request): |
49 | 98 | raise NotImplementedError() |
50 | 99 |
|
| 100 | + @staticmethod |
| 101 | + def get_parameter(form, param): |
| 102 | + return (get_option(form, "form_parameters") or {}).get(param, None) |
| 103 | + |
51 | 104 |
|
52 | 105 | @register |
53 | 106 | class SaveToDBAction(FormAction): |
@@ -90,36 +143,78 @@ def execute(self, form, request): |
90 | 143 | SAVE_TO_DB_ACTION = next(iter(_action_registry)) if _action_registry else None |
91 | 144 |
|
92 | 145 |
|
| 146 | +def validate_recipients(value): |
| 147 | + recipients = value.split() |
| 148 | + for recipient in recipients: |
| 149 | + EmailValidator(message=_("Please replace \"%s\" by a valid email address.") % recipient)(recipient) |
| 150 | + |
| 151 | + |
93 | 152 | @register |
94 | 153 | class SendMailAction(FormAction): |
95 | | - verbose_name = _("Send email to administrators") |
96 | | - recipients = None |
| 154 | + class Meta: |
| 155 | + entangled_fields = { |
| 156 | + "action_parameters": [ |
| 157 | + "sendemail_recipients", |
| 158 | + "sendemail_template", |
| 159 | + ] |
| 160 | + } |
| 161 | + |
| 162 | + verbose_name = _("Send email") |
97 | 163 | from_mail = None |
98 | 164 | template = "djangocms_form_builder/actions/mail.html" |
99 | 165 | subject = _("%(form_name)s form submission") |
100 | 166 |
|
| 167 | + sendemail_recipients = forms.CharField( |
| 168 | + label=_("Mail recipients"), |
| 169 | + required=False, |
| 170 | + initial="", |
| 171 | + validators=[ |
| 172 | + validate_recipients, |
| 173 | + ], |
| 174 | + help_text=_("Space or newline separated list of email addresses."), |
| 175 | + widget=forms.Textarea, |
| 176 | + ) |
| 177 | + |
| 178 | + sendemail_template = forms.ChoiceField( |
| 179 | + label=_("Mail template set"), |
| 180 | + required=True, |
| 181 | + initial=MAIL_TEMPLATE_SETS[0][0], |
| 182 | + choices=MAIL_TEMPLATE_SETS, |
| 183 | + widget=forms.Select if len(MAIL_TEMPLATE_SETS) > 1 else forms.HiddenInput, |
| 184 | + ) |
| 185 | + |
101 | 186 | def execute(self, form, request): |
| 187 | + recipients = (self.get_parameter(form, "sendemail_recipients") or []).split() |
| 188 | + template_set = self.get_parameter(form, "sendemail_template") or "default" |
102 | 189 | context = dict( |
103 | 190 | cleaned_data=form.cleaned_data, |
| 191 | + form_name=getattr(form.Meta, "verbose_name", ""), |
104 | 192 | user=request.user, |
105 | 193 | user_agent=request.headers["User-Agent"], |
106 | 194 | referer=request.headers["Referer"], |
107 | 195 | ) |
108 | | - html_message = render_to_string(self.template, context) |
109 | | - message = strip_tags(html_message) |
110 | | - form_name = form.cleaned_data["form_name"].replace("-", " ").capitalize() |
111 | | - if self.recipients is None: |
| 196 | + |
| 197 | + html_message = render_to_string(f"djangocms_form_builder/mails/{template_set}/mail_html.html", context) |
| 198 | + try: |
| 199 | + message = render_to_string(f"djangocms_form_builder/mails/{template_set}/mail.txt", context) |
| 200 | + except TemplateDoesNotExist: |
| 201 | + message = strip_tags(html_message) |
| 202 | + try: |
| 203 | + subject = render_to_string(f"djangocms_form_builder/mails/{template_set}/subject.txt", context) |
| 204 | + except TemplateDoesNotExist: |
| 205 | + subject = self.subject % dict(form_name=context["form_name"]) |
| 206 | + if not recipients: |
112 | 207 | mail_admins( |
113 | | - self.subject % dict(form_name=form_name), |
| 208 | + subject, |
114 | 209 | message, |
115 | 210 | fail_silently=True, |
116 | 211 | html_message=html_message, |
117 | 212 | ) |
118 | 213 | else: |
119 | 214 | send_mail( |
120 | | - self.subject % dict(form_name=form_name), |
| 215 | + subject, |
121 | 216 | message, |
122 | | - self.recipients, |
| 217 | + recipients, |
123 | 218 | self.from_mail, |
124 | 219 | fail_silently=True, |
125 | 220 | html_message=html_message, |
|
0 commit comments