285 lines
11 KiB
Python
285 lines
11 KiB
Python
|
from datetime import datetime
|
||
|
from DateTime import DateTime
|
||
|
|
||
|
from urllib import quote as url_quote
|
||
|
|
||
|
from zope.interface import implements
|
||
|
|
||
|
from zope.component import createObject, getMultiAdapter, queryUtility
|
||
|
|
||
|
from zope.viewlet.interfaces import IViewlet
|
||
|
|
||
|
from Acquisition import aq_inner, aq_parent, aq_base
|
||
|
|
||
|
from AccessControl import getSecurityManager
|
||
|
|
||
|
from Products.Five.browser import BrowserView
|
||
|
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
||
|
|
||
|
from Products.CMFCore.utils import getToolByName
|
||
|
|
||
|
from Products.CMFPlone import PloneMessageFactory as _
|
||
|
from Products.statusmessages.interfaces import IStatusMessage
|
||
|
|
||
|
from plone.registry.interfaces import IRegistry
|
||
|
|
||
|
from plone.app.layout.viewlets.common import ViewletBase
|
||
|
|
||
|
from plone.app.discussion.comment import CommentFactory
|
||
|
from plone.app.discussion.interfaces import IConversation, IComment, IReplies, IDiscussionSettings
|
||
|
|
||
|
|
||
|
|
||
|
class View(BrowserView):
|
||
|
"""Comment View
|
||
|
"""
|
||
|
|
||
|
def __call__(self):
|
||
|
# Redirect from /path/to/object/++conversation++default/123456789
|
||
|
# to /path/to/object#comment-123456789
|
||
|
comment_id = aq_parent(self).id
|
||
|
#self.request.response.redirect(aq_parent(aq_parent(aq_parent(self))).absolute_url() + '#comment-' + comment_id)
|
||
|
self.request.response.redirect(aq_parent(aq_parent(aq_parent(self))).absolute_url() + '#' + comment_id)
|
||
|
|
||
|
class CommentsViewlet(ViewletBase):
|
||
|
"""Discussion Viewlet
|
||
|
"""
|
||
|
|
||
|
implements(IViewlet)
|
||
|
|
||
|
template = ViewPageTemplateFile('comments.pt')
|
||
|
|
||
|
def update(self):
|
||
|
super(CommentsViewlet, self).update()
|
||
|
self.portal_discussion = getToolByName(self.context, 'portal_discussion', None)
|
||
|
self.portal_membership = getToolByName(self.context, 'portal_membership', None)
|
||
|
|
||
|
def can_reply(self):
|
||
|
return getSecurityManager().checkPermission('Reply to item', aq_inner(self.context))
|
||
|
|
||
|
def can_manage(self):
|
||
|
return getSecurityManager().checkPermission('Manage portal', aq_inner(self.context))
|
||
|
|
||
|
def is_discussion_allowed(self):
|
||
|
context = aq_inner(self.context)
|
||
|
conversation = IConversation(context)
|
||
|
return conversation.enabled
|
||
|
|
||
|
def get_replies(self, workflow_actions=False):
|
||
|
context = aq_inner(self.context)
|
||
|
conversation = IConversation(context)
|
||
|
|
||
|
def replies_with_workflow_actions():
|
||
|
# Return dict with workflow actions
|
||
|
#context = aq_inner(self.context)
|
||
|
wf = getToolByName(context, 'portal_workflow')
|
||
|
|
||
|
for r in conversation.getThreads():
|
||
|
comment_obj = r['comment']
|
||
|
# list all possible workflow actions
|
||
|
actions = [a for a in wf.listActionInfos(object=comment_obj)
|
||
|
if a['category'] == 'workflow' and a['allowed']]
|
||
|
r = r.copy()
|
||
|
r['actions'] = actions
|
||
|
yield r
|
||
|
|
||
|
# Return all direct replies
|
||
|
if conversation.total_comments > 0:
|
||
|
if workflow_actions:
|
||
|
return replies_with_workflow_actions()
|
||
|
else:
|
||
|
return conversation.getThreads()
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
|
||
|
def get_commenter_home_url(self, username):
|
||
|
if username is None:
|
||
|
return None
|
||
|
else:
|
||
|
return "%s/author/%s" % (self.context.portal_url(), username)
|
||
|
|
||
|
def get_commenter_portrait(self, username):
|
||
|
|
||
|
if username is None:
|
||
|
# return the default user image if no username is given
|
||
|
return 'defaultUser.gif'
|
||
|
else:
|
||
|
portal_membership = getToolByName(self.context, 'portal_membership', None)
|
||
|
return portal_membership.getPersonalPortrait(username).absolute_url();
|
||
|
|
||
|
def anonymous_discussion_allowed(self):
|
||
|
# Check if anonymous comments are allowed in the registry
|
||
|
registry = queryUtility(IRegistry)
|
||
|
settings = registry.forInterface(IDiscussionSettings)
|
||
|
return settings.anonymous_comments
|
||
|
|
||
|
def show_commenter_image(self):
|
||
|
# Check if showing commenter image is enabled in the registry
|
||
|
registry = queryUtility(IRegistry)
|
||
|
settings = registry.forInterface(IDiscussionSettings)
|
||
|
return settings.show_commenter_image
|
||
|
|
||
|
def is_anonymous(self):
|
||
|
return self.portal_state.anonymous()
|
||
|
|
||
|
def login_action(self):
|
||
|
return '%s/login_form?came_from=%s' % (self.navigation_root_url, url_quote(self.request.get('URL', '')),)
|
||
|
|
||
|
def format_time(self, time):
|
||
|
# We have to transform Python datetime into Zope DateTime
|
||
|
# before we can call toLocalizedTime.
|
||
|
util = getToolByName(self.context, 'translation_service')
|
||
|
zope_time = DateTime(time.year, time.month, time.day, time.hour, time.minute, time.second)
|
||
|
return util.toLocalizedTime(zope_time, long_format=True)
|
||
|
|
||
|
class AddComment(BrowserView):
|
||
|
"""Add a comment to a conversation
|
||
|
"""
|
||
|
|
||
|
def __call__(self):
|
||
|
|
||
|
if self.request.has_key('form.button.AddComment'):
|
||
|
|
||
|
context = aq_inner(self.context)
|
||
|
|
||
|
subject = self.request.get('subject')
|
||
|
text = self.request.get('body_text')
|
||
|
author_username = self.request.get('author_username')
|
||
|
author_email = self.request.get('author_email')
|
||
|
|
||
|
# Check the form input
|
||
|
if author_username == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Username field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if author_email == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Email field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if subject == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Subject field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if text == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Comment field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
|
||
|
# The add-comment view is called on the conversation object
|
||
|
conversation = context
|
||
|
|
||
|
# Create the comment
|
||
|
comment = CommentFactory()
|
||
|
comment.title = subject
|
||
|
comment.text = text
|
||
|
|
||
|
portal_membership = getToolByName(context, 'portal_membership')
|
||
|
|
||
|
if portal_membership.isAnonymousUser():
|
||
|
comment.creator = author_username
|
||
|
comment.author_name = author_username
|
||
|
comment.author_email = author_email
|
||
|
comment.creation_date = comment.modification_date = datetime.now()
|
||
|
else:
|
||
|
member = portal_membership.getAuthenticatedMember()
|
||
|
fullname = member.getProperty('fullname')
|
||
|
if fullname == '' or None:
|
||
|
comment.creator = member.id
|
||
|
else:
|
||
|
comment.creator = fullname
|
||
|
comment.author_username = member.getUserName()
|
||
|
comment.author_name = member.getProperty('fullname')
|
||
|
comment.author_email = member.getProperty('email')
|
||
|
comment.creation_date = comment.modification_date = datetime.now()
|
||
|
|
||
|
# Add comment to the conversation
|
||
|
comment_id = conversation.addComment(comment)
|
||
|
|
||
|
# Redirect to comment (inside a content object page)
|
||
|
#self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#comment-' + str(comment_id))
|
||
|
self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#' + str(comment_id))
|
||
|
|
||
|
class ReplyToComment(BrowserView):
|
||
|
"""Reply to a comment
|
||
|
"""
|
||
|
|
||
|
def __call__(self):
|
||
|
|
||
|
context = aq_inner(self.context)
|
||
|
|
||
|
if self.request.has_key('form.button.AddComment'):
|
||
|
|
||
|
reply_to_comment_id = self.request.get('form.reply_to_comment_id')
|
||
|
|
||
|
subject = self.request.get('subject')
|
||
|
text = self.request.get('body_text')
|
||
|
author_username = self.request.get('author_username')
|
||
|
author_email = self.request.get('author_email')
|
||
|
|
||
|
# Check the form input
|
||
|
if author_username == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Username field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if author_email == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Email field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if subject == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Subject field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
if text == '':
|
||
|
IStatusMessage(self.request).addStatusMessage(\
|
||
|
_("Comment field is empty."),
|
||
|
type="info")
|
||
|
return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
|
||
|
|
||
|
# The add-comment view is called on the conversation object
|
||
|
conversation = context
|
||
|
|
||
|
# Fetch the comment we want to reply to
|
||
|
comment_to_reply_to = conversation.get(reply_to_comment_id)
|
||
|
|
||
|
replies = IReplies(comment_to_reply_to)
|
||
|
|
||
|
# Create the comment
|
||
|
comment = CommentFactory()
|
||
|
comment.title = subject
|
||
|
comment.text = text
|
||
|
|
||
|
portal_membership = getToolByName(context, 'portal_membership')
|
||
|
|
||
|
if portal_membership.isAnonymousUser():
|
||
|
comment.creator = author_username
|
||
|
comment.author_name = author_username
|
||
|
comment.author_email = author_email
|
||
|
comment.creation_date = comment.modification_date = datetime.now()
|
||
|
else:
|
||
|
member = portal_membership.getAuthenticatedMember()
|
||
|
fullname = member.getProperty('fullname')
|
||
|
if fullname == '' or None:
|
||
|
comment.creator = member.id
|
||
|
else:
|
||
|
comment.creator = fullname
|
||
|
comment.author_username = member.getUserName()
|
||
|
comment.author_name = member.getProperty('fullname')
|
||
|
comment.author_email = member.getProperty('email')
|
||
|
comment.creation_date = comment.modification_date = datetime.now()
|
||
|
|
||
|
# Add the reply to the comment
|
||
|
new_re_id = replies.addComment(comment)
|
||
|
|
||
|
# Redirect to comment (inside a content object page)
|
||
|
#self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#comment-' + str(reply_to_comment_id))
|
||
|
# Todo: Temporarily remove the "#comment-" to fix a bug
|
||
|
# in CMFPlone/skins/plone_ecmascript/form_tabbing.js
|
||
|
self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#' + str(reply_to_comment_id))
|