[Testbot] Plone 5.0 - Python 2.7 - Build # 1607 - Fixed! - 0 failure(s)
jenkins at plone.org
jenkins at plone.org
Mon Feb 17 18:59:30 UTC 2014
-------------------------------------------------------------------------------
Plone 5.0 - Python 2.7 - Build # 1607 - Fixed!
-------------------------------------------------------------------------------
http://jenkins.plone.org/job/plone-5.0-python-2.7/1607/
-------------------------------------------------------------------------------
CHANGES
-------------------------------------------------------------------------------
Repository: Products.CMFPlone
Branch: refs/heads/master
Date: 2014-02-17T10:14:10-08:00
Author: Elizabeth Leddy (eleddy) <eleddy at umich.edu>
Commit: https://github.com/plone/Products.CMFPlone/commit/8db491bd8f57459cc601875fbd8d09dbe22e496c
Revert "Merge pull request #179 from plone/remove_sendto_cleanedup"
This reverts commit ae4a51caee497b62fb2e9f8c8534158ae26be51b, reversing
changes made to 1453b0c517615a576465efbaaae69ae06c5028ae.
Files changed:
A Products/CMFPlone/skins/plone_form_scripts/sendto.cpy
A Products/CMFPlone/skins/plone_form_scripts/sendto.cpy.metadata
A Products/CMFPlone/skins/plone_form_scripts/validate_sendto.vpy
A Products/CMFPlone/skins/plone_forms/sendto_form.cpt
A Products/CMFPlone/skins/plone_forms/sendto_form.cpt.metadata
A Products/CMFPlone/skins/plone_templates/sendto_template.pt
M Products/CMFPlone/PloneTool.py
M Products/CMFPlone/browser/configure.zcml
M Products/CMFPlone/browser/interfaces.py
M Products/CMFPlone/profiles/default/rolemap.xml
D Products/CMFPlone/browser/sendto.py
D Products/CMFPlone/browser/templates/sendto_template.pt
diff --git a/Products/CMFPlone/PloneTool.py b/Products/CMFPlone/PloneTool.py
index cc769f2..e9071dc 100644
--- a/Products/CMFPlone/PloneTool.py
+++ b/Products/CMFPlone/PloneTool.py
@@ -49,6 +49,9 @@
import LinkIntegrityNotificationException
+AllowSendto = 'Allow sendto'
+permissions.setDefaultRoles(AllowSendto, ('Anonymous', 'Manager', ))
+
_marker = utils._marker
_icons = {}
@@ -160,6 +163,27 @@ def getMailHost(self):
"""
return getattr(aq_parent(self), 'MailHost')
+ security.declareProtected(AllowSendto, 'sendto')
+ def sendto(self, send_to_address, send_from_address, comment,
+ subject='Plone', **kwargs):
+ # Sends a link of a page to someone.
+ host = self.getMailHost()
+ template = getattr(self, 'sendto_template')
+ portal = getToolByName(self, 'portal_url').getPortalObject()
+ encoding = portal.getProperty('email_charset')
+ if 'envelope_from' in kwargs:
+ envelope_from = kwargs['envelope_from']
+ else:
+ envelope_from = send_from_address
+ # Cook from template
+ message = template(self, send_to_address=send_to_address,
+ send_from_address=send_from_address,
+ comment=comment, subject=subject, **kwargs)
+ message = message.encode(encoding)
+ host.send(message, mto=send_to_address,
+ mfrom=envelope_from, subject=subject,
+ charset='utf-8')
+
security.declarePublic('validateSingleNormalizedEmailAddress')
def validateSingleNormalizedEmailAddress(self, address):
"""Lower-level function to validate a single normalized email address,
diff --git a/Products/CMFPlone/browser/configure.zcml b/Products/CMFPlone/browser/configure.zcml
index bf36f23..259e02f 100644
--- a/Products/CMFPlone/browser/configure.zcml
+++ b/Products/CMFPlone/browser/configure.zcml
@@ -12,17 +12,6 @@
<allow interface="plone.app.layout.navigation.interfaces.INavigationQueryBuilder" />
</class>
- <permission
- id="Products.CMFPlone.AllowSendto"
- title="Allow sendto" />
-
- <browser:page
- for="*"
- name="sendto_form"
- class=".sendto.SendToForm"
- permission="Products.CMFPlone.AllowSendto"
- />
-
<browser:page
for="*"
name="breadcrumbs_view"
diff --git a/Products/CMFPlone/browser/interfaces.py b/Products/CMFPlone/browser/interfaces.py
index 7b3442f..b003206 100644
--- a/Products/CMFPlone/browser/interfaces.py
+++ b/Products/CMFPlone/browser/interfaces.py
@@ -1,11 +1,7 @@
-from zope import schema
from zope.interface import Interface
import zope.deferredimport
-from Products.CMFPlone import PloneMessageFactory as _
-
-
# This is used as a persistent marker interface, we need to provide an upgrade
# step to update the class reference before removing it.
zope.deferredimport.deprecated(
@@ -312,31 +308,3 @@ def bodyClass(template, view):
""" returns template or view name to mark body tag with
template-${template_id} CSS class
"""
-
-
-class ISendToForm(Interface):
- """ Interface for describing the 'sendto' form """
-
- send_to_address = schema.TextLine(
- title=_(u'label_send_to_mail',
- default=u'Send to'),
- description=_(u'help_send_to_mail',
- default=u'The e-mail address to send this link to.'),
- required=True
- )
-
- send_from_address = schema.TextLine(
- title=_(u'label_send_from',
- default=u'From'),
- description=_(u'help_send_from',
- default=u'Your email address.'),
- required=True
- )
-
- comment = schema.Text(
- title=_(u'label_comment',
- default=u'Comment'),
- description=_(u'help_comment_to_link',
- default=u'A comment about this link.'),
- required=False
- )
diff --git a/Products/CMFPlone/browser/sendto.py b/Products/CMFPlone/browser/sendto.py
deleted file mode 100644
index aa97cf3..0000000
--- a/Products/CMFPlone/browser/sendto.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from Products.CMFPlone import PloneMessageFactory as _
-from Products.CMFPlone.utils import pretty_title_or_id
-from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
-from Products.MailHost.interfaces import IMailHost
-from Products.statusmessages.interfaces import IStatusMessage
-
-from ZODB.POSException import ConflictError
-
-from plone.z3cform import layout
-
-from zope.component import getMultiAdapter
-from zope.component import getUtility
-
-from z3c.form import form
-from z3c.form import field
-from z3c.form import button
-
-from interfaces import ISendToForm
-
-import logging
-
-logger = logging.getLogger("Plone")
-
-
-class SendToForm(form.Form):
- label = _(u'heading_send_page_to',
- default=u'Send this page to someone')
-
- description = _(u'description_send_page_url_to',
- default=u'Fill in the email address of your '
- u'friend, and we will send an email '
- u'that contains a link to this page.')
-
- fields = field.Fields(ISendToForm)
- ignoreContext = True
-
- mail_template = ViewPageTemplateFile('templates/sendto_template.pt')
-
- # XXX: Add validation, but the plan is the fields should be
- # changed to the Email field that is to be provided by
- # plone schema
-
- @button.buttonAndHandler(_(u'label_send', default='Send'),
- name='send')
- def handle_send(self, action):
- data, errors = self.extractData()
- if errors:
- IStatusMessage(self.request).addStatusMessage(
- self.formErrorsMessage,
- type=u'error'
- )
- return
-
- portal_state = getMultiAdapter(
- (self.context, self.request),
- name=u'plone_portal_state'
- )
- site = portal_state.portal()
-
- context_state = getMultiAdapter(
- (self.context, self.request),
- name=u'plone_context_state'
- )
- url = context_state.view_url()
-
- send_from_address = data.get('send_from_address')
- send_to_address = data.get('send_to_address')
- subject = pretty_title_or_id(self, self.context)
- title = pretty_title_or_id(self, self.context)
- description = self.context.Description()
- comment = data.get('comment', None)
- envelope_from = site.getProperty('email_from_address', None)
-
- try:
- # Sends a link of a page to someone.
- host = getUtility(IMailHost)
- encoding = site.getProperty('email_charset')
-
- if not envelope_from:
- envelope_from = send_from_address
-
- # Cook from template
- message = self.mail_template(
- self,
- send_to_address=send_to_address,
- send_from_address=send_from_address,
- comment=comment,
- subject=subject,
- title=title,
- description=description
- )
-
- message = message.encode(encoding)
-
- host.send(
- message,
- mto=send_to_address,
- mfrom=envelope_from,
- subject=subject,
- charset='utf-8'
- )
-
- except ConflictError:
- raise
- except Exception as e:
- # TODO To many things could possibly go wrong. So we catch all.
- logger.info("Unable to send mail: " + str(e))
- IStatusMessage(self.request).addStatusMessage(
- _(u'Unable to send mail.'),
- type=u'error'
- )
- return
-
- IStatusMessage(self.request).addStatusMessage(
- _(u'Mail sent.'),
- type=u'info'
- )
-
-send_to_form = layout.wrap_form(SendToForm)
diff --git a/Products/CMFPlone/browser/templates/sendto_template.pt b/Products/CMFPlone/browser/templates/sendto_template.pt
deleted file mode 100644
index a83e4d2..0000000
--- a/Products/CMFPlone/browser/templates/sendto_template.pt
+++ /dev/null
@@ -1,30 +0,0 @@
-<div xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
- xmlns:tal="http://xml.zope.org/namespaces/tal"
- xmlns:metal="http://xml.zope.org/namespaces/metal"
- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
- i18n:domain="plone"
- tal:omit-tag=""
- tal:define="utool nocall:context/portal_url;
- charset context/email_charset|string:utf-8;
- dummy python:request.RESPONSE.setHeader('Content-Type', 'text/html;;charset=%s' % charset)"
-><div i18n:translate="sendto_mailtemplate_body" tal:omit-tag="">
-This link is sent to you from <span i18n:name="portal_url" tal:omit-tag="" tal:replace="structure utool" />
-
-You are receiving this mail because someone read a page at
-<span i18n:name="portal_title" tal:omit-tag="" tal:replace="structure utool/Title" />
-and thought it might interest you.
-
-It is sent by <span i18n:name="from_address" tal:omit-tag="" tal:replace="structure options/send_from_address"
-/> with the following comment:
-"<span i18n:name="comment" tal:omit-tag="" tal:replace="structure options/comment | nothing" />"
-
-<span i18n:name="document_title" tal:omit-tag="" tal:replace="structure options/title | context/Title" />
-
-<span i18n:name="document_description" tal:omit-tag="" tal:replace="structure options/description | context/Description" />
-
-<span i18n:name="document_url" tal:omit-tag="" tal:replace="structure options/url | context/absolute_url" />
-</div>
---
-<span tal:replace="structure context/email_from_name" />
-
-</div>
diff --git a/Products/CMFPlone/profiles/default/rolemap.xml b/Products/CMFPlone/profiles/default/rolemap.xml
index de9a084..ecde4b9 100644
--- a/Products/CMFPlone/profiles/default/rolemap.xml
+++ b/Products/CMFPlone/profiles/default/rolemap.xml
@@ -38,6 +38,7 @@
<role name="Contributor"/>
</permission>
<permission name="Allow sendto" acquire="True">
+ <role name="Anonymous"/>
<role name="Manager"/>
<role name="Site Administrator"/>
<role name="Member"/>
diff --git a/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy b/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy
new file mode 100644
index 0000000..7b8ae19
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy
@@ -0,0 +1,58 @@
+## Controller Python Script "sendto"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=
+##title=Send an URL to a friend
+
+REQUEST = context.REQUEST
+
+from Products.CMFPlone.utils import transaction_note
+from Products.CMFPlone.PloneTool import AllowSendto
+from Products.CMFCore.utils import getToolByName
+from Products.CMFPlone import PloneMessageFactory as _
+from ZODB.POSException import ConflictError
+
+plone_utils = getToolByName(context, 'plone_utils')
+mtool = getToolByName(context, 'portal_membership')
+site = getToolByName(context, 'portal_url').getPortalObject()
+pretty_title_or_id = plone_utils.pretty_title_or_id
+
+if not mtool.checkPermission(AllowSendto, context):
+ plone_utils.addPortalMessage(_(u'You are not allowed to send this link.'),
+ 'error')
+ return state.set(status='failure')
+
+# Find the view action.
+context_state = context.restrictedTraverse("@@plone_context_state")
+url = context_state.view_url()
+
+variables = {'send_from_address' : REQUEST.send_from_address,
+ 'send_to_address' : REQUEST.send_to_address,
+ 'subject' : pretty_title_or_id(context),
+ 'url' : url,
+ 'title' : pretty_title_or_id(context),
+ 'description' : context.Description(),
+ 'comment' : REQUEST.get('comment', None),
+ 'envelope_from' : site.getProperty('email_from_address'),
+ }
+
+try:
+ plone_utils.sendto(**variables)
+except ConflictError:
+ raise
+except: # TODO To many things could possibly go wrong. So we catch all.
+ exception = plone_utils.exceptionString()
+ message = _(u'Unable to send mail: ${exception}',
+ mapping={u'exception': exception})
+ plone_utils.addPortalMessage(message, 'error')
+ return state.set(status='failure')
+
+tmsg = 'Sent page %s to %s' % (url, REQUEST.send_to_address)
+transaction_note(tmsg)
+
+plone_utils.addPortalMessage(_(u'Mail sent.'))
+return state
diff --git a/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy.metadata b/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy.metadata
new file mode 100644
index 0000000..80bb542
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_form_scripts/sendto.cpy.metadata
@@ -0,0 +1,6 @@
+[validators]
+validators=validate_sendto
+
+[actions]
+action.success = redirect_to_action:string:view
+action.failure = redirect_to_action:string:view
diff --git a/Products/CMFPlone/skins/plone_form_scripts/validate_sendto.vpy b/Products/CMFPlone/skins/plone_form_scripts/validate_sendto.vpy
new file mode 100644
index 0000000..f2f1fa0
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_form_scripts/validate_sendto.vpy
@@ -0,0 +1,39 @@
+## Controller Script Python "validate_sendto"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=send_to_address='',send_from_address=''
+##title=validates the email adresses
+
+from Products.CMFPlone import PloneMessageFactory as _
+plone_utils=context.plone_utils
+
+if not send_to_address:
+ state.setError('send_to_address',
+ _(u'Please submit an email address.'),
+ 'email_required')
+
+if not plone_utils.validateEmailAddresses(send_to_address):
+ state.setError('send_to_address',
+ _(u'Please submit a valid email address.'),
+ 'email_required')
+
+if not send_from_address:
+ state.setError('send_from_address',
+ _(u'Please submit an email address.'),
+ 'email_required')
+
+if not plone_utils.validateSingleEmailAddress(send_from_address):
+ state.setError('send_from_address',
+ _(u'Please submit a valid email address.'),
+ 'email_required')
+
+if state.getErrors():
+ context.plone_utils.addPortalMessage(
+ _(u'Please correct the indicated errors.'), 'error')
+ return state.set(status='failure')
+else:
+ return state
diff --git a/Products/CMFPlone/skins/plone_forms/sendto_form.cpt b/Products/CMFPlone/skins/plone_forms/sendto_form.cpt
new file mode 100644
index 0000000..f4140eb
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_forms/sendto_form.cpt
@@ -0,0 +1,126 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ metal:use-macro="context/main_template/macros/master"
+ i18n:domain="plone">
+
+<metal:block fill-slot="top_slot"
+ tal:define="dummy python:request.set('disable_border',1)" />
+
+ <metal:head fill-slot="head_slot">
+ <meta name="robots" content="noindex,follow" />
+ </metal:head>
+
+ <body>
+
+ <metal:main fill-slot="main"
+ tal:define="errors options/state/getErrors;">
+
+ <h1 class="documentFirstHeading"
+ i18n:translate="heading_send_page_to">Send this page to someone</h1>
+
+ <div class="documentDescription"
+ i18n:translate="description_send_page_url_to">
+ Fill in the email address of your friend, and we will send an email
+ that contains a link to this page.
+ </div>
+
+ <div id="content-core">
+ <form name="sendto_form"
+ class="enableAutoFocus"
+ action="sendto_form"
+ method="post"
+ enctype="multipart/form-data"
+ tal:attributes="action string:${context/@@plone_context_state/object_url}/${template/getId}">
+
+ <fieldset>
+
+ <legend i18n:translate="legend_address_info">Address info</legend>
+
+ <div class="field"
+ tal:define="error errors/send_to_address|nothing;"
+ tal:attributes="class python:test(error, 'field error', 'field')">
+
+ <label for="send_to_address" i18n:translate="label_send_to_mail">Send to</label>
+
+ <span class="fieldRequired" title="Required"
+ i18n:attributes="title title_required;"
+ i18n:translate="label_required">(Required)</span>
+
+ <div class="formHelp" i18n:translate="help_send_to_mail">
+ The e-mail address to send this link to.
+ </div>
+
+ <div tal:content="error">Validation error output</div>
+
+ <input type="text"
+ id="send_to_address"
+ name="send_to_address"
+ size="25"
+ tal:attributes="value request/send_to_address | nothing;"
+ />
+ </div>
+
+ <div class="field"
+ tal:define="error errors/send_from_address|nothing;"
+ tal:attributes="class python:test(error, 'field error', 'field')">
+
+ <label for="send_from_address" i18n:translate="label_send_from">From</label>
+
+ <span class="fieldRequired" title="Required"
+ i18n:attributes="title title_required;"
+ i18n:translate="label_required">(Required)</span>
+
+ <div class="formHelp" i18n:translate="help_send_from">
+ Your email address.
+ </div>
+
+ <div tal:content="error">Validation error output</div>
+
+ <input type="text"
+ id="send_from_address"
+ name="send_from_address"
+ size="25"
+ tal:define="member context/@@plone_portal_state/member;"
+ tal:attributes="value python: request.get('send_from_address', member.getProperty('email',''));"
+ />
+ </div>
+
+ <div class="field">
+ <label for="comment" i18n:translate="label_comment">Comment</label>
+
+ <div class="formHelp" i18n:translate="help_comment_to_link">
+ A comment about this link.
+ </div>
+
+ <textarea cols="80"
+ rows="5"
+ id="comment"
+ name="comment"
+ tal:content="request/comment | nothing"
+ >
+ Comment
+ </textarea>
+ </div>
+
+ <div class="formControls">
+ <input class="context"
+ type="submit"
+ name="form.button.Send"
+ value="Send"
+ i18n:attributes="value label_send;"
+ />
+ </div>
+
+ <input type="hidden" name="form.submitted" value="1" />
+
+ </fieldset>
+
+ </form>
+ </div>
+
+ </metal:main>
+
+ </body>
+</html>
diff --git a/Products/CMFPlone/skins/plone_forms/sendto_form.cpt.metadata b/Products/CMFPlone/skins/plone_forms/sendto_form.cpt.metadata
new file mode 100644
index 0000000..96d0516
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_forms/sendto_form.cpt.metadata
@@ -0,0 +1,9 @@
+[default]
+title=Send this page to somebody
+
+[validators]
+validators=validate_sendto
+
+[actions]
+action.success=traverse_to:string:sendto
+action.failure=traverse_to:string:sendto_form
diff --git a/Products/CMFPlone/skins/plone_templates/sendto_template.pt b/Products/CMFPlone/skins/plone_templates/sendto_template.pt
new file mode 100644
index 0000000..a83e4d2
--- /dev/null
+++ b/Products/CMFPlone/skins/plone_templates/sendto_template.pt
@@ -0,0 +1,30 @@
+<div xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ i18n:domain="plone"
+ tal:omit-tag=""
+ tal:define="utool nocall:context/portal_url;
+ charset context/email_charset|string:utf-8;
+ dummy python:request.RESPONSE.setHeader('Content-Type', 'text/html;;charset=%s' % charset)"
+><div i18n:translate="sendto_mailtemplate_body" tal:omit-tag="">
+This link is sent to you from <span i18n:name="portal_url" tal:omit-tag="" tal:replace="structure utool" />
+
+You are receiving this mail because someone read a page at
+<span i18n:name="portal_title" tal:omit-tag="" tal:replace="structure utool/Title" />
+and thought it might interest you.
+
+It is sent by <span i18n:name="from_address" tal:omit-tag="" tal:replace="structure options/send_from_address"
+/> with the following comment:
+"<span i18n:name="comment" tal:omit-tag="" tal:replace="structure options/comment | nothing" />"
+
+<span i18n:name="document_title" tal:omit-tag="" tal:replace="structure options/title | context/Title" />
+
+<span i18n:name="document_description" tal:omit-tag="" tal:replace="structure options/description | context/Description" />
+
+<span i18n:name="document_url" tal:omit-tag="" tal:replace="structure options/url | context/absolute_url" />
+</div>
+--
+<span tal:replace="structure context/email_from_name" />
+
+</div>
-------------------------------------------------------------------------------
More information about the Testbot
mailing list