From fad818069cee13ef078561b80fbaaa3d6138a0f5 Mon Sep 17 00:00:00 2001
From: Jorran Wit <jorrandewit@outlook.com>
Date: Fri, 23 Dec 2016 23:26:54 +0100
Subject: [PATCH] Move vet_commentary_request logic to form

Logic from vet_commentary_request has been moved
to the VetCommentaryForm form. Further moved some
code to improve DRY.
---
 commentaries/forms.py | 102 +++++++++++++++++++++++++++----
 commentaries/views.py | 135 +++++++++++++++++++++---------------------
 2 files changed, 161 insertions(+), 76 deletions(-)

diff --git a/commentaries/forms.py b/commentaries/forms.py
index f0dcdf3a3..acf9558fa 100644
--- a/commentaries/forms.py
+++ b/commentaries/forms.py
@@ -5,17 +5,15 @@ from .models import Commentary
 
 from scipost.models import Contributor
 
-COMMENTARY_ACTION_CHOICES = (
-    (0, 'modify'),
-    (1, 'accept'),
-    (2, 'refuse (give reason below)'),
-    )
-
+REFUSAL_EMPTY = 0
+REFUSAL_PAPER_EXISTS = -1
+REFUSAL_UNTRACEBLE = -2
+REFUSAL_ARXIV_EXISTS = -3
 COMMENTARY_REFUSAL_CHOICES = (
-    (0, '-'),
-    (-1, 'a commentary on this paper already exists'),
-    (-2, 'this paper cannot be traced'),
-    (-3, 'there exists a more revent version of this arXiv preprint'),
+    (REFUSAL_EMPTY, '-'),
+    (REFUSAL_PAPER_EXISTS, 'a commentary on this paper already exists'),
+    (REFUSAL_UNTRACEBLE, 'this paper cannot be traced'),
+    (REFUSAL_ARXIV_EXISTS, 'there exists a more revent version of this arXiv preprint'),
     )
 commentary_refusal_dict = dict(COMMENTARY_REFUSAL_CHOICES)
 
@@ -32,6 +30,7 @@ class IdentifierToQueryForm(forms.Form):
 
 
 class RequestCommentaryForm(forms.ModelForm):
+    """Create new valid Commetary by user request"""
     existing_commentary = None
 
     class Meta:
@@ -54,6 +53,7 @@ class RequestCommentaryForm(forms.ModelForm):
         self.fields['pub_abstract'].widget.attrs.update({'cols': 100})
 
     def clean(self, *args, **kwargs):
+        """Check if form is valid and contains an unique identifier"""
         cleaned_data = super(RequestCommentaryForm, self).clean(*args, **kwargs)
 
         # Either Arxiv-ID or DOI is given
@@ -92,6 +92,26 @@ class RequestCommentaryForm(forms.ModelForm):
 
 
 class VetCommentaryForm(forms.Form):
+    """Process an unvetted Commentary request.
+
+    This form will provide fields to let the user
+    process a Commentary that is unvetted. On success,
+    the Commentary is either accepted or deleted from
+    the database.
+
+    Keyword arguments:
+    commentary_id -- the Commentary.id to process (required)
+    user -- User instance of the vetting user (required)
+
+    """
+    ACTION_MODIFY = 0
+    ACTION_ACCEPT = 1
+    ACTION_REFUSE = 2
+    COMMENTARY_ACTION_CHOICES = (
+        (ACTION_MODIFY, 'modify'),
+        (ACTION_ACCEPT, 'accept'),
+        (ACTION_REFUSE, 'refuse (give reason below)'),
+    )
     action_option = forms.ChoiceField(widget=forms.RadioSelect,
                                       choices=COMMENTARY_ACTION_CHOICES,
                                       required=True, label='Action')
@@ -99,6 +119,68 @@ class VetCommentaryForm(forms.Form):
     email_response_field = forms.CharField(widget=forms.Textarea(
         attrs={'rows': 5, 'cols': 40}), label='Justification (optional)', required=False)
 
+    def __init__(self, *args, **kwargs):
+        """Pop and save keyword arguments if set, return form instance"""
+        self.commentary_id = kwargs.pop('commentary_id', None)
+        self.user = kwargs.pop('user', None)
+        self.is_cleaned = False
+        return super(VetCommentaryForm, self).__init__(*args, **kwargs)
+
+    def clean(self, *args, **kwargs):
+        """Check valid form and keyword arguments given"""
+        cleaned_data = super(VetCommentaryForm, self).clean(*args, **kwargs)
+
+        # Check valid `commentary_id`
+        if not self.commentary_id:
+            self.add_error(None, 'No `commentary_id` provided')
+            return cleaned_data
+        else:
+            self.commentary = Commentary.objects.get(pk=self.commentary_id)
+
+        # Check valid `user`
+        if not self.user:
+            self.add_error(None, 'No `user` provided')
+            return cleaned_data
+
+        self.is_cleaned = True
+        return cleaned_data
+
+    def _form_is_cleaned(self):
+        """Raise ValueError if form isn't validated"""
+        if not self.is_cleaned:
+            raise ValueError(('VetCommentaryForm could not be processed '
+                'because the data didn\'t validate'))
+
+    def get_commentary(self):
+        """Return Commentary if available"""
+        self._form_is_cleaned()
+        return self.commentary
+
+    def process_commentary(self):
+        """Vet the commentary or delete it from the database"""
+        self._form_is_cleaned()
+
+        if self.commentary_is_accepted():
+            self.commentary.vetted = True
+            self.commentary.vetted_by = Contributor.objects.get(user=self.user)
+            self.commentary.save()
+            return self.commentary
+        elif self.commentary_is_modified() or self.commentary_is_refused():
+            self.commentary.delete()
+            return None
+
+    def commentary_is_accepted(self):
+        self._form_is_cleaned()
+        return int(self.cleaned_data['action_option']) == self.ACTION_ACCEPT
+
+    def commentary_is_modified(self):
+        self._form_is_cleaned()
+        return int(self.cleaned_data['action_option']) == self.ACTION_MODIFY
+
+    def commentary_is_refused(self):
+        self._form_is_cleaned()
+        return int(self.cleaned_data['action_option']) == self.ACTION_REFUSE
+
 
 class CommentarySearchForm(forms.Form):
     """Search for Commentary specified by user"""
diff --git a/commentaries/views.py b/commentaries/views.py
index 506fd838f..015d35798 100644
--- a/commentaries/views.py
+++ b/commentaries/views.py
@@ -140,7 +140,7 @@ def prefill_using_DOI(request):
 
 @permission_required('scipost.can_request_commentary_pages', raise_exception=True)
 def prefill_using_identifier(request):
-    """ Probes arXiv with the identifier, to pre-fill the form. """
+    """Probes arXiv with the identifier, to pre-fill the form"""
     if request.method == "POST":
         identifierform = IdentifierToQueryForm(request.POST)
         if identifierform.is_valid():
@@ -226,6 +226,7 @@ def prefill_using_identifier(request):
 
 @permission_required('scipost.can_vet_commentary_requests', raise_exception=True)
 def vet_commentary_requests(request):
+    """Show the first commentary thats awaiting vetting"""
     contributor = Contributor.objects.get(user=request.user)
     commentary_to_vet = Commentary.objects.awaiting_vetting().first() # only handle one at a time
     form = VetCommentaryForm()
@@ -235,74 +236,76 @@ def vet_commentary_requests(request):
 @permission_required('scipost.can_vet_commentary_requests', raise_exception=True)
 def vet_commentary_request_ack(request, commentary_id):
     if request.method == 'POST':
-        form = VetCommentaryForm(request.POST)
-        commentary = Commentary.objects.get(pk=commentary_id)
+        form = VetCommentaryForm(request.POST, user=request.user, commentary_id=commentary_id)
         if form.is_valid():
-            if form.cleaned_data['action_option'] == '1':
-                # accept the commentary as is
-                commentary.vetted = True
-                commentary.vetted_by = Contributor.objects.get(user=request.user)
-                commentary.latest_activity = timezone.now()
-                commentary.save()
-                email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' '
-                              + commentary.requested_by.user.last_name
-                              + ', \n\nThe Commentary Page you have requested, '
-                              'concerning publication with title '
-                              + commentary.pub_title + ' by ' + commentary.author_list
-                              + ', has been activated at https://scipost.org/commentary/'
-                              + str(commentary.arxiv_or_DOI_string)
-                              + '. You are now welcome to submit your comments.'
-                              '\n\nThank you for your contribution, \nThe SciPost Team.')
-                emailmessage = EmailMessage('SciPost Commentary Page activated', email_text,
-                                            'SciPost commentaries <commentaries@scipost.org>',
-                                            [commentary.requested_by.user.email],
-                                            ['commentaries@scipost.org'],
-                                            reply_to=['commentaries@scipost.org'])
-                emailmessage.send(fail_silently=False)
-            elif form.cleaned_data['action_option'] == '0':
-                # re-edit the form starting from the data provided
-                form2 = RequestCommentaryForm(initial={'pub_title': commentary.pub_title,
-                                                       'arxiv_link': commentary.arxiv_link,
-                                                       'pub_DOI_link': commentary.pub_DOI_link,
-                                                       'author_list': commentary.author_list,
-                                                       'pub_date': commentary.pub_date,
-                                                       'pub_abstract': commentary.pub_abstract})
-                commentary.delete()
-                email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' '
-                              + commentary.requested_by.user.last_name
-                              + ', \n\nThe Commentary Page you have requested, '
-                              'concerning publication with title ' + commentary.pub_title
-                              + ' by ' + commentary.author_list
-                              + ', has been activated (with slight modifications to your submitted details).'
-                              ' You are now welcome to submit your comments.'
-                              '\n\nThank you for your contribution, \nThe SciPost Team.')
-                emailmessage = EmailMessage('SciPost Commentary Page activated', email_text,
-                                            'SciPost commentaries <commentaries@scipost.org>',
-                                            [commentary.requested_by.user.email],
-                                            ['commentaries@scipost.org'],
-                                            reply_to=['commentaries@scipost.org'])
-                emailmessage.send(fail_silently=False)
-                context = {'form': form2 }
-                return render(request, 'commentaries/request_commentary.html', context)
-            elif form.cleaned_data['action_option'] == '2':
-                # the commentary request is simply rejected
+            # Get commentary
+            commentary = form.get_commentary()
+            if form.commentary_is_accepted():
+                # Accept the commentary as is
+                email_args = (
+                    'SciPost Commentary Page activated',
+                    ('Dear ' + title_dict[commentary.requested_by.title] + ' '
+                        + commentary.requested_by.user.last_name
+                        + ', \n\nThe Commentary Page you have requested, '
+                        'concerning publication with title '
+                        + commentary.pub_title + ' by ' + commentary.author_list
+                        + ', has been activated at https://scipost.org/commentary/'
+                        + str(commentary.arxiv_or_DOI_string)
+                        + '. You are now welcome to submit your comments.'
+                        '\n\nThank you for your contribution, \nThe SciPost Team.')
+                )
+            elif form.commentary_is_modified():
+                # Re-edit the form starting from the data provided
+                email_args = (
+                    'SciPost Commentary Page activated',
+                    ('Dear ' + title_dict[commentary.requested_by.title] + ' '
+                        + commentary.requested_by.user.last_name
+                        + ', \n\nThe Commentary Page you have requested, '
+                        'concerning publication with title ' + commentary.pub_title
+                        + ' by ' + commentary.author_list
+                        + ', has been activated (with slight modifications to your submitted details).'
+                        ' You are now welcome to submit your comments.'
+                        '\n\nThank you for your contribution, \nThe SciPost Team.')
+                )
+
+                request_commentary_form = RequestCommentaryForm(initial={
+                    'pub_title': commentary.pub_title,
+                    'arxiv_link': commentary.arxiv_link,
+                    'pub_DOI_link': commentary.pub_DOI_link,
+                    'author_list': commentary.author_list,
+                    'pub_date': commentary.pub_date,
+                    'pub_abstract': commentary.pub_abstract
+                })
+            elif form.commentary_is_refused():
+                # The commentary request is simply rejected
                 email_text = ('Dear ' + title_dict[commentary.requested_by.title] + ' '
-                              + commentary.requested_by.user.last_name
-                              + ', \n\nThe Commentary Page you have requested, '
-                              'concerning publication with title '
-                              + commentary.pub_title + ' by ' + commentary.author_list
-                              + ', has not been activated for the following reason: '
-                              + commentary_refusal_dict[int(form.cleaned_data['refusal_reason'])]
-                              + '.\n\nThank you for your interest, \nThe SciPost Team.')
+                        + commentary.requested_by.user.last_name
+                        + ', \n\nThe Commentary Page you have requested, '
+                        'concerning publication with title '
+                        + commentary.pub_title + ' by ' + commentary.author_list
+                        + ', has not been activated for the following reason: '
+                        + commentary_refusal_dict[int(form.cleaned_data['refusal_reason'])]
+                        + '.\n\nThank you for your interest, \nThe SciPost Team.')
+
                 if form.cleaned_data['email_response_field']:
-                    email_text += '\n\nFurther explanations: ' + form.cleaned_data['email_response_field']
-                emailmessage = EmailMessage('SciPost Commentary Page activated', email_text,
-                                            'SciPost commentaries <commentaries@scipost.org>',
-                                            [commentary.requested_by.user.email],
-                                            ['commentaries@scipost.org'],
-                                            reply_to=['comentaries@scipost.org'])
-                emailmessage.send(fail_silently=False)
-                commentary.delete()
+                    email_text += '\n\nFurther explanations: '
+                    email_text += form.cleaned_data['email_response_field']
+
+                email_args = (
+                    'SciPost Commentary Page activated',
+                    email_text
+                )
+
+            # Send email and process form
+            email_args += ([commentary.requested_by.user.email], ['commentaries@scipost.org'],)
+            emailmessage = EmailMessage(*email_args, reply_to=['commentaries@scipost.org'])
+            emailmessage.send(fail_silently=False)
+            commentary = form.process_commentary()
+
+            if form.commentary_is_modified():
+                # For a modified commentary, redirect to request_commentary_form
+                context = {'form': request_commentary_form}
+                return render(request, 'commentaries/request_commentary.html', context)
 
     context = {'ack_header': 'SciPost Commentary request vetted.',
                'followup_message': 'Return to the ',
-- 
GitLab