[web/views] Move massmailing to its own cube (closes #2788086)
authorRémi Cardona <remi.cardona@logilab.fr>
Tue, 02 Apr 2013 12:13:06 +0200
changeset 8849 7da8339cd768
parent 8848 08bb2dd18fd2
child 8850 4032499c701e
[web/views] Move massmailing to its own cube (closes #2788086)
doc/3.17.rst
web/data/cubicweb.mailform.css
web/test/unittest_form.py
web/test/unittest_views_actions.py
web/test/unittest_views_basecontrollers.py
web/views/basecontrollers.py
web/views/massmailing.py
--- a/doc/3.17.rst	Tue Apr 02 18:15:24 2013 +0200
+++ b/doc/3.17.rst	Tue Apr 02 12:13:06 2013 +0200
@@ -14,13 +14,16 @@
 API changes
 -----------
 
+* drop typed_eid() in favour of int() (see `#2742462 <http://www.cubicweb.org/2742462>`_)
+
 * The SIOC views and adapters have been removed from CubicWeb and moved to the
   `sioc` cube.
 
 * The web page embedding views and adapters have been removed from CubicWeb and
   moved to the `embed` cube.
 
-* drop typed_eid() in favour of int() (see `#2742462 <http://www.cubicweb.org/2742462>`_)
+* The email sending views and controllers have been removed from CubicWeb and
+  moved to the `massmailing` cube.
 
 
 
--- a/web/data/cubicweb.mailform.css	Tue Apr 02 18:15:24 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* styles for the email form (views/massmailing.py)
- *
- *  :organization: Logilab
- *  :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
- *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
- */
-
-form#sendmail {
-  border: 1px solid #DBDCE3;
-  background-color: #E9F5F7;
-  font-family:Verdana,Tahoma,Arial,sans-serif;
-  padding: 1em 1ex;
-}
-
-table.headersform {
-  width: 100%;
-}
-
-form#sendmail td#buttonbar {
-  padding: 0.5ex 0ex;
-}
-
-table.headersform td.hlabel {
-  padding-top: 0.5ex;
-  color: #444444;
-  text-align: right;
-}
-
-table.headersform td.hvalue {
-  padding-top: 0.5ex;
-  padding-left: 0.5em;
-  width: 100%;
-}
-
-table.headersform td.hvalue input#mailsubj {
-  width: 47em; 
-}
-
-form#sendmail div#toolbar {
-  margin: 0.5em 0em;
-  height: 29px;
-}
-
-form#sendmail div#toolbar ul {
-  list-style-image: none;
-  list-style-position: outside;
-  list-style-type:none;
-  margin:0px;
-  padding:0px;
-  /* border: 1px solid #DBDCE3; */
-}
-
-form#sendmail div#toolbar li {
-  background: none;
-  padding-left: 1em;
-  float: left;
-}
-
-form#sendmail div#toolbar li a {
-  font-family: Verdana,Tahoma,Arial,sans-serif;
-  color: #444444;
-}
-
-div#substitutions {
-  padding-left: 1em;
-}
--- a/web/test/unittest_form.py	Tue Apr 02 18:15:24 2013 +0200
+++ b/web/test/unittest_form.py	Tue Apr 02 12:13:06 2013 +0200
@@ -122,14 +122,6 @@
         data = form.render(row=0, rtype='content', formid='base', action='edit_rtype')
         self.assertTrue('content_format' in data)
 
-    # form view tests #########################################################
-
-    def test_massmailing_formview(self):
-        self.execute('INSERT EmailAddress X: X address L + "@cubicweb.org", '
-                     'U use_email X WHERE U is CWUser, U login L')
-        rset = self.execute('CWUser X')
-        self.view('massmailing', rset, template=None)
-
 
     # form tests ##############################################################
 
--- a/web/test/unittest_views_actions.py	Tue Apr 02 18:15:24 2013 +0200
+++ b/web/test/unittest_views_actions.py	Tue Apr 02 12:13:06 2013 +0200
@@ -30,16 +30,6 @@
         vaction = [action for action in actions if action.__regid__ == 'view'][0]
         self.assertEqual(vaction.url(), 'http://testing.fr/cubicweb/view?rql=CWUser%20X')
 
-    def test_sendmail_action(self):
-        req = self.request()
-        rset = self.execute('Any X WHERE X login "admin"', req=req)
-        actions = self.vreg['actions'].poss_visible_objects(req, rset=rset)
-        self.assertTrue([action for action in actions if action.__regid__ == 'sendemail'])
-        self.login('anon')
-        req = self.request()
-        rset = self.execute('Any X WHERE X login "anon"', req=req)
-        actions = self.vreg['actions'].poss_visible_objects(req, rset=rset)
-        self.assertFalse([action for action in actions if action.__regid__ == 'sendemail'])
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_views_basecontrollers.py	Tue Apr 02 18:15:24 2013 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Tue Apr 02 12:13:06 2013 +0200
@@ -544,21 +544,6 @@
         self.vreg['controllers'].select('reportbug', self.request(description='hop'))
 
 
-class SendMailControllerTC(CubicWebTC):
-
-    def test_not_usable_by_guest(self):
-        self.assertRaises(NoSelectableObject,
-                          self.vreg['controllers'].select, 'sendmail', self.request())
-        self.vreg['controllers'].select('sendmail',
-                                        self.request(subject='toto',
-                                                     recipient='toto@logilab.fr',
-                                                     mailbody='hop'))
-        self.login('anon')
-        self.assertRaises(NoSelectableObject,
-                          self.vreg['controllers'].select, 'sendmail', self.request())
-
-
-
 class AjaxControllerTC(CubicWebTC):
     tested_controller = 'ajax'
 
--- a/web/views/basecontrollers.py	Tue Apr 02 18:15:24 2013 +0200
+++ b/web/views/basecontrollers.py	Tue Apr 02 12:13:06 2013 +0200
@@ -271,7 +271,6 @@
         return ajax_controller.publish(rset)
 
 
-# XXX move to massmailing
 class MailBugReportController(Controller):
     __regid__ = 'reportbug'
     __select__ = match_form_params('description')
--- a/web/views/massmailing.py	Tue Apr 02 18:15:24 2013 +0200
+++ b/web/views/massmailing.py	Tue Apr 02 12:13:06 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -17,161 +17,24 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Mass mailing handling: send mail to entities adaptable to IEmailable"""
 
-__docformat__ = "restructuredtext en"
-_ = unicode
-
-import operator
-from functools import reduce
-
-from cubicweb.predicates import (is_instance, authenticated_user,
-                                adaptable, match_form_params)
-from cubicweb.view import EntityView
-from cubicweb.web import (Redirect, stdmsgs, controller, action,
-                          form, formfields as ff)
-from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton
-from cubicweb.web.views import forms, formrenderers
-
-
-class SendEmailAction(action.Action):
-    __regid__ = 'sendemail'
-    # XXX should check email is set as well
-    __select__ = (action.Action.__select__
-                  & authenticated_user()
-                  & adaptable('IEmailable'))
-
-    title = _('send email')
-    category = 'mainactions'
-
-    def url(self):
-        params = {'vid': 'massmailing', '__force_display': 1}
-        if 'rql' in self._cw.form:
-            params['rql'] = self._cw.form['rql']
-        return self._cw.build_url(self._cw.relative_path(includeparams=False),
-                                  **params)
-
-
-def recipient_vocabulary(form, field):
-    vocab = [(entity.cw_adapt_to('IEmailable').get_email(), unicode(entity.eid))
-             for entity in form.cw_rset.entities()]
-    return [(label, value) for label, value in vocab if label]
+try:
+    from cubes.massmailing.views import (SendEmailAction,
+                                         recipient_vocabulary,
+                                         MassMailingForm,
+                                         MassMailingFormRenderer,
+                                         MassMailingFormView,
+                                         SendMailController)
 
 
-class MassMailingForm(forms.FieldsForm):
-    __regid__ = 'massmailing'
-
-    needs_js = ('cubicweb.edition.js', 'cubicweb.widgets.js',)
-    needs_css = ('cubicweb.mailform.css')
-    domid = 'sendmail'
-    action = 'sendmail'
-
-    sender = ff.StringField(widget=TextInput({'disabled': 'disabled'}),
-                            label=_('From:'),
-                            value=lambda form, field: '%s <%s>' % (
-                                form._cw.user.dc_title(),
-                                form._cw.user.cw_adapt_to('IEmailable').get_email()))
-    recipient = ff.StringField(widget=CheckBox(), label=_('Recipients:'),
-                               choices=recipient_vocabulary,
-                               value= lambda form, field: [entity.eid for entity in form.cw_rset.entities()
-                                                           if entity.cw_adapt_to('IEmailable').get_email()])
-    subject = ff.StringField(label=_('Subject:'), max_length=256)
-    mailbody = ff.StringField(widget=AjaxWidget(wdgtype='TemplateTextField',
-                                                inputid='mailbody'))
-
-    form_buttons = [ImgButton('sendbutton', "javascript: $('#sendmail').submit()",
-                              _('send email'), 'SEND_EMAIL_ICON'),
-                    ImgButton('cancelbutton', "javascript: history.back()",
-                              _(stdmsgs.BUTTON_CANCEL[0]), stdmsgs.BUTTON_CANCEL[1])]
-    form_renderer_id = __regid__
-
-    def __init__(self, *args, **kwargs):
-        super(MassMailingForm, self).__init__(*args, **kwargs)
-        field = self.field_by_name('mailbody')
-        field.widget.attrs['cubicweb:variables'] = ','.join(self.get_allowed_substitutions())
-
-    def get_allowed_substitutions(self):
-        attrs = []
-        for coltype in self.cw_rset.column_types(0):
-            entity = self._cw.vreg['etypes'].etype_class(coltype)(self._cw)
-            attrs.append(entity.cw_adapt_to('IEmailable').allowed_massmail_keys())
-        return sorted(reduce(operator.and_, attrs))
-
-    def build_substitutions_help(self):
-        insertLink = u'<a href="javascript: cw.widgets.insertText(\'%%(%s)s\', \'emailarea\');">%%(%s)s</a>'
-        substs = (u'<div class="substitution">%s</div>' % (insertLink % (subst, subst))
-                  for subst in self.get_allowed_substitutions())
-        helpmsg = self._cw._('You can use any of the following substitutions in your text')
-        return u'<div id="substitutions"><span>%s</span>%s</div>' % (
-            helpmsg, u'\n'.join(substs))
-
-
-class MassMailingFormRenderer(formrenderers.FormRenderer):
-    __regid__ = 'massmailing'
+    from logilab.common.deprecation import class_moved, moved
 
-    def _render_fields(self, fields, w, form):
-        w(u'<table class="headersform">')
-        for field in fields:
-            if field.name == 'mailbody':
-                w(u'</table>')
-                self._render_toolbar(w, form)
-                w(u'<table>')
-                w(u'<tr><td><div>')
-            else:
-                w(u'<tr>')
-                w(u'<td class="hlabel">%s</td>' % self.render_label(form, field))
-                w(u'<td class="hvalue">')
-            w(field.render(form, self))
-            if field.name == 'mailbody':
-                w(u'</div></td>')
-                w(u'<td>%s</td>' % form.build_substitutions_help())
-                w(u'</tr>')
-            else:
-                w(u'</td></tr>')
-        w(u'</table>')
-
-    def _render_toolbar(self, w, form):
-        w(u'<div id="toolbar">')
-        w(u'<ul>')
-        for button in form.form_buttons:
-            w(u'<li>%s</li>' % button.render(form))
-        w(u'</ul>')
-        w(u'</div>')
-
-    def render_buttons(self, w, form):
-        pass
-
-
-class MassMailingFormView(form.FormViewMixIn, EntityView):
-    __regid__ = 'massmailing'
-    __select__ = authenticated_user() & adaptable('IEmailable')
-
-    def call(self):
-        form = self._cw.vreg['forms'].select('massmailing', self._cw,
-                                             rset=self.cw_rset)
-        form.render(w=self.w)
-
-
-class SendMailController(controller.Controller):
-    __regid__ = 'sendmail'
-    __select__ = authenticated_user() & match_form_params('recipient', 'mailbody', 'subject')
-
-    def recipients(self):
-        """returns an iterator on email's recipients as entities"""
-        eids = self._cw.form['recipient']
-        # eids may be a string if only one recipient was specified
-        if isinstance(eids, basestring):
-            rset = self._cw.execute('Any X WHERE X eid %(x)s', {'x': eids})
-        else:
-            rset = self._cw.execute('Any X WHERE X eid in (%s)' % (','.join(eids)))
-        return rset.entities()
-
-    def publish(self, rset=None):
-        # XXX this allows users with access to an cubicweb instance to use it as
-        # a mail relay
-        body = self._cw.form['mailbody']
-        subject = self._cw.form['subject']
-        for recipient in self.recipients():
-            iemailable = recipient.cw_adapt_to('IEmailable')
-            text = body % iemailable.as_email_context()
-            self.sendmail(iemailable.get_email(), subject, text)
-        url = self._cw.build_url(__message=self._cw._('emails successfully sent'))
-        raise Redirect(url)
+    msg = '[3.17] cubicweb.web.views.massmailing moved to cubes.massmailing.views'
+    SendEmailAction = class_moved(SendEmailAction, message=msg)
+    recipient_vocabulary = moved('cubes.massmailing.views', 'recipient_vocabulary')
+    MassMailingForm = class_moved(MassMailingForm, message=msg)
+    MassMailingFormRenderer = class_moved(MassMailingFormRenderer, message=msg)
+    MassMailingFormView = class_moved(MassMailingFormView, message=msg)
+    SendMailController = class_moved(SendMailController, message=msg)
+except ImportError:
+    from cubicweb.web import LOGGER
+    LOGGER.warning('[3.17] massmailing extracted to cube massmailing that was not found. try installing it.')