2013-09-19 10:39:52 +02:00
|
|
|
from AccessControl import getSecurityManager
|
2016-02-05 01:39:53 +01:00
|
|
|
from AccessControl import Unauthorized
|
2015-05-03 08:16:39 +02:00
|
|
|
from Acquisition import aq_inner
|
|
|
|
from Acquisition import aq_parent
|
2022-05-01 23:14:00 +02:00
|
|
|
from plone.app.discussion.events import CommentDeletedEvent
|
2018-10-24 16:49:22 +02:00
|
|
|
from plone.app.discussion.events import CommentPublishedEvent
|
2019-12-08 20:01:40 +01:00
|
|
|
from plone.app.discussion.events import CommentTransitionEvent
|
2016-02-05 01:39:53 +01:00
|
|
|
from plone.app.discussion.interfaces import _
|
|
|
|
from plone.app.discussion.interfaces import IComment
|
|
|
|
from plone.app.discussion.interfaces import IReplies
|
2015-05-03 08:16:39 +02:00
|
|
|
from Products.CMFCore.utils import getToolByName
|
2009-06-10 22:14:44 +02:00
|
|
|
from Products.Five.browser import BrowserView
|
|
|
|
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
2009-07-07 10:00:41 +02:00
|
|
|
from Products.statusmessages.interfaces import IStatusMessage
|
2018-09-27 11:26:41 +02:00
|
|
|
from zope.event import notify
|
2009-12-19 16:03:12 +01:00
|
|
|
|
2010-01-22 17:28:00 +01:00
|
|
|
|
2019-12-05 21:55:23 +01:00
|
|
|
# Translations for generated values in buttons
|
|
|
|
# States
|
2022-05-01 23:14:09 +02:00
|
|
|
_("comment_pending", default="pending")
|
2019-12-10 15:51:28 +01:00
|
|
|
# _('comment_approved', default='published')
|
2022-05-01 23:14:09 +02:00
|
|
|
_("comment_published", default="published")
|
|
|
|
_("comment_rejected", default="rejected")
|
|
|
|
_("comment_spam", default="marked as spam")
|
2019-12-05 21:55:23 +01:00
|
|
|
# Transitions
|
2022-05-01 23:14:09 +02:00
|
|
|
_("Recall")
|
|
|
|
_("Approve")
|
|
|
|
_("Reject")
|
|
|
|
_("Spam")
|
2020-06-18 11:58:24 +02:00
|
|
|
PMF = _
|
2019-12-05 21:55:23 +01:00
|
|
|
|
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
class TranslationHelper(BrowserView):
|
|
|
|
def translate(self, text=""):
|
|
|
|
return _(text)
|
|
|
|
|
|
|
|
def translate_comment_review_state(self, rs):
|
2020-06-18 11:58:24 +02:00
|
|
|
# use PMF instead of _ here so i18ndude doesn't extract "comment_"
|
|
|
|
return PMF("comment_" + rs, default=rs)
|
2019-12-08 20:01:40 +01:00
|
|
|
|
|
|
|
|
2009-06-10 22:14:44 +02:00
|
|
|
class View(BrowserView):
|
2019-12-05 21:55:23 +01:00
|
|
|
"""Show comment moderation view."""
|
|
|
|
|
2022-05-01 23:14:09 +02:00
|
|
|
template = ViewPageTemplateFile("moderation.pt")
|
2009-08-20 04:11:57 +02:00
|
|
|
try:
|
2022-05-01 23:14:09 +02:00
|
|
|
template.id = "@@moderate-comments"
|
2009-08-20 04:11:57 +02:00
|
|
|
except AttributeError:
|
|
|
|
# id is not writeable in Zope 2.12
|
|
|
|
pass
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 21:55:23 +01:00
|
|
|
def __init__(self, context, request):
|
2022-05-01 23:14:41 +02:00
|
|
|
super().__init__(context, request)
|
2022-05-01 23:14:09 +02:00
|
|
|
self.workflowTool = getToolByName(self.context, "portal_workflow")
|
2019-12-08 20:01:40 +01:00
|
|
|
self.transitions = []
|
2019-12-05 21:55:23 +01:00
|
|
|
|
2009-06-10 22:14:44 +02:00
|
|
|
def __call__(self):
|
2022-05-01 23:14:09 +02:00
|
|
|
self.request.set("disable_border", True)
|
|
|
|
self.request.set("review_state", self.request.get("review_state", "pending"))
|
2009-06-10 22:14:44 +02:00
|
|
|
return self.template()
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 21:55:23 +01:00
|
|
|
def comments(self):
|
|
|
|
"""Return comments of defined review_state.
|
|
|
|
|
|
|
|
review_state is string or list of strings.
|
|
|
|
"""
|
2022-05-01 23:14:09 +02:00
|
|
|
catalog = getToolByName(self.context, "portal_catalog")
|
|
|
|
if self.request.review_state == "all":
|
|
|
|
return catalog(
|
|
|
|
object_provides=IComment.__identifier__,
|
|
|
|
sort_on="created",
|
|
|
|
sort_order="reverse",
|
|
|
|
)
|
|
|
|
return catalog(
|
|
|
|
object_provides=IComment.__identifier__,
|
|
|
|
review_state=self.request.review_state,
|
|
|
|
sort_on="created",
|
|
|
|
sort_order="reverse",
|
|
|
|
)
|
2019-12-05 21:55:23 +01:00
|
|
|
|
2009-10-18 15:12:52 +02:00
|
|
|
def moderation_enabled(self):
|
2019-12-05 21:55:23 +01:00
|
|
|
"""Return true if a review workflow is enabled on 'Discussion Item'
|
|
|
|
content type.
|
|
|
|
|
|
|
|
A 'review workflow' is characterized by implementing a 'pending'
|
|
|
|
workflow state.
|
2009-10-18 15:12:52 +02:00
|
|
|
"""
|
2022-05-01 23:14:09 +02:00
|
|
|
workflows = self.workflowTool.getChainForPortalType("Discussion Item")
|
2019-12-08 20:01:40 +01:00
|
|
|
if workflows:
|
|
|
|
comment_workflow = self.workflowTool[workflows[0]]
|
2022-05-01 23:14:09 +02:00
|
|
|
if "pending" in comment_workflow.states:
|
2011-04-27 19:41:07 +02:00
|
|
|
return True
|
2011-04-27 21:33:00 +02:00
|
|
|
return False
|
2009-06-10 22:14:44 +02:00
|
|
|
|
2019-09-30 16:43:19 +02:00
|
|
|
@property
|
2019-12-05 21:55:23 +01:00
|
|
|
def moderation_multiple_state_enabled(self):
|
|
|
|
"""Return true if a 'review multiple state workflow' is enabled on
|
|
|
|
'Discussion Item' content type.
|
|
|
|
|
|
|
|
A 'review multipe state workflow' is characterized by implementing
|
|
|
|
a 'rejected' workflow state and a 'spam' workflow state.
|
2019-09-30 16:43:19 +02:00
|
|
|
"""
|
2022-05-01 23:14:09 +02:00
|
|
|
workflows = self.workflowTool.getChainForPortalType("Discussion Item")
|
2019-12-08 20:01:40 +01:00
|
|
|
if workflows:
|
|
|
|
comment_workflow = self.workflowTool[workflows[0]]
|
2022-05-01 23:14:09 +02:00
|
|
|
if "spam" in comment_workflow.states:
|
2019-09-30 16:43:19 +02:00
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2019-12-05 21:55:23 +01:00
|
|
|
def allowed_transitions(self, obj=None):
|
2019-12-08 20:01:40 +01:00
|
|
|
"""Return allowed workflow transitions for obj.
|
2019-12-05 21:55:23 +01:00
|
|
|
|
|
|
|
Example: pending
|
|
|
|
|
2020-01-06 18:02:23 +01:00
|
|
|
[{'id': 'mark_as_spam', 'url': 'http://localhost:8083/PloneRejected/testfolder/testpage/++conversation++default/1575415863542780/content_status_modify?workflow_action=mark_as_spam', 'icon': '', 'category': 'workflow', 'transition': <TransitionDefinition at /PloneRejected/portal_workflow/comment_review_workflow/transitions/mark_as_spam>, 'title': 'Spam', 'link_target': None, 'visible': True, 'available': True, 'allowed': True},
|
2019-12-05 21:55:23 +01:00
|
|
|
{'id': 'publish',
|
|
|
|
'url': 'http://localhost:8083/PloneRejected/testfolder/testpage/++conversation++default/1575415863542780/content_status_modify?workflow_action=publish',
|
|
|
|
'icon': '',
|
|
|
|
'category': 'workflow',
|
2020-01-06 18:02:23 +01:00
|
|
|
'transition': <TransitionDefinition at /PloneRejected/portal_workflow/comment_review_workflow/transitions/publish>,
|
2019-12-05 21:55:23 +01:00
|
|
|
'title': 'Approve',
|
|
|
|
'link_target': None, 'visible': True, 'available': True, 'allowed': True},
|
2020-01-06 18:02:23 +01:00
|
|
|
{'id': 'reject', 'url': 'http://localhost:8083/PloneRejected/testfolder/testpage/++conversation++default/1575415863542780/content_status_modify?workflow_action=reject', 'icon': '', 'category': 'workflow', 'transition': <TransitionDefinition at /PloneRejected/portal_workflow/comment_review_workflow/transitions/reject>, 'title': 'Reject', 'link_target': None, 'visible': True, 'available': True, 'allowed': True}]
|
2019-12-05 21:55:23 +01:00
|
|
|
"""
|
|
|
|
if obj:
|
|
|
|
transitions = [
|
2022-05-01 23:14:09 +02:00
|
|
|
a
|
|
|
|
for a in self.workflowTool.listActionInfos(object=obj)
|
|
|
|
if a["category"] == "workflow" and a["allowed"]
|
|
|
|
]
|
2019-12-05 21:55:23 +01:00
|
|
|
return transitions
|
|
|
|
|
|
|
|
|
2010-12-08 18:45:11 +01:00
|
|
|
class ModerateCommentsEnabled(BrowserView):
|
|
|
|
def __call__(self):
|
2010-12-16 00:52:56 +01:00
|
|
|
"""Returns true if a 'review workflow' is enabled on 'Discussion Item'
|
2022-05-01 23:14:09 +02:00
|
|
|
content type. A 'review workflow' is characterized by implementing
|
|
|
|
a 'pending' workflow state.
|
2010-12-08 18:45:11 +01:00
|
|
|
"""
|
|
|
|
context = aq_inner(self.context)
|
2022-05-01 23:14:09 +02:00
|
|
|
workflowTool = getToolByName(context, "portal_workflow", None)
|
|
|
|
comment_workflow = workflowTool.getChainForPortalType("Discussion Item")
|
2011-04-27 19:41:07 +02:00
|
|
|
if comment_workflow:
|
|
|
|
comment_workflow = comment_workflow[0]
|
|
|
|
comment_workflow = workflowTool[comment_workflow]
|
2022-05-01 23:14:09 +02:00
|
|
|
if "pending" in comment_workflow.states:
|
2011-04-27 19:41:07 +02:00
|
|
|
return True
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2011-04-27 21:33:00 +02:00
|
|
|
return False
|
2010-12-08 18:45:11 +01:00
|
|
|
|
2010-12-16 00:52:56 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
class DeleteComment(BrowserView):
|
2010-10-05 17:14:12 +02:00
|
|
|
"""Delete a comment from a conversation.
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
This view is always called directly on the comment object:
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
http://nohost/front-page/++conversation++default/1286289644723317/\
|
|
|
|
@@moderate-delete-comment
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
Each table row (comment) in the moderation view contains a hidden input
|
|
|
|
field with the absolute URL of the content object:
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-12-16 00:52:56 +01:00
|
|
|
<input type="hidden"
|
2010-10-05 17:14:12 +02:00
|
|
|
value="http://nohost/front-page/++conversation++default/\
|
2010-12-16 00:52:56 +01:00
|
|
|
1286289644723317"
|
2010-10-05 17:14:12 +02:00
|
|
|
name="selected_obj_paths:list">
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
This absolute URL is called from a jQuery method that is bind to the
|
|
|
|
'delete' button of the table row. See javascripts/moderation.js for more
|
2010-12-16 00:52:56 +01:00
|
|
|
details.
|
2009-06-26 16:57:45 +02:00
|
|
|
"""
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
def __call__(self):
|
2011-04-22 19:09:09 +02:00
|
|
|
comment = aq_inner(self.context)
|
|
|
|
conversation = aq_parent(comment)
|
|
|
|
content_object = aq_parent(conversation)
|
2013-09-19 10:39:52 +02:00
|
|
|
# conditional security
|
|
|
|
# base ZCML condition zope2.deleteObject allows 'delete own object'
|
|
|
|
# modify this for 'delete_own_comment_allowed' controlpanel setting
|
|
|
|
if self.can_delete(comment):
|
|
|
|
del conversation[comment.id]
|
|
|
|
content_object.reindexObject()
|
2018-10-24 16:49:22 +02:00
|
|
|
notify(CommentDeletedEvent(self.context, comment))
|
2013-09-19 10:39:52 +02:00
|
|
|
IStatusMessage(self.context.REQUEST).addStatusMessage(
|
2022-05-01 23:14:09 +02:00
|
|
|
_("Comment deleted."), type="info"
|
|
|
|
)
|
2011-04-22 19:09:09 +02:00
|
|
|
came_from = self.context.REQUEST.HTTP_REFERER
|
2012-04-12 13:06:05 +02:00
|
|
|
# if the referrer already has a came_from in it, don't redirect back
|
2022-05-01 23:14:09 +02:00
|
|
|
if (
|
|
|
|
len(came_from) == 0
|
|
|
|
or "came_from=" in came_from
|
|
|
|
or not getToolByName(content_object, "portal_url").isURLInPortal(came_from)
|
|
|
|
):
|
2011-04-22 19:09:09 +02:00
|
|
|
came_from = content_object.absolute_url()
|
|
|
|
return self.context.REQUEST.RESPONSE.redirect(came_from)
|
2009-07-07 10:00:41 +02:00
|
|
|
|
2013-09-19 10:39:52 +02:00
|
|
|
def can_delete(self, reply):
|
2014-09-20 16:02:48 +02:00
|
|
|
"""Returns true if current user has the 'Delete comments'
|
|
|
|
permission.
|
2013-09-19 10:39:52 +02:00
|
|
|
"""
|
2022-05-01 23:14:09 +02:00
|
|
|
return getSecurityManager().checkPermission("Delete comments", aq_inner(reply))
|
2013-09-19 10:39:52 +02:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
|
2012-05-07 13:02:07 +02:00
|
|
|
class DeleteOwnComment(DeleteComment):
|
2015-05-03 08:41:24 +02:00
|
|
|
"""Delete an own comment if it has no replies.
|
|
|
|
|
|
|
|
Following conditions have to be true for a user to be able to delete his
|
|
|
|
comments:
|
2012-05-07 13:02:07 +02:00
|
|
|
* "Delete own comments" permission
|
|
|
|
* no replies to the comment
|
|
|
|
* Owner role directly assigned on the comment object
|
|
|
|
"""
|
|
|
|
|
2014-09-05 11:11:54 +02:00
|
|
|
def could_delete(self, comment=None):
|
2022-05-01 23:14:09 +02:00
|
|
|
"""Returns true if the comment could be deleted if it had no replies."""
|
2012-05-07 13:02:07 +02:00
|
|
|
sm = getSecurityManager()
|
2014-09-05 11:11:54 +02:00
|
|
|
comment = comment or aq_inner(self.context)
|
2012-05-07 13:02:07 +02:00
|
|
|
userid = sm.getUser().getId()
|
2022-05-01 23:14:09 +02:00
|
|
|
return sm.checkPermission(
|
|
|
|
"Delete own comments", comment
|
|
|
|
) and "Owner" in comment.get_local_roles_for_userid(userid)
|
2012-05-07 13:02:07 +02:00
|
|
|
|
2014-09-05 11:11:54 +02:00
|
|
|
def can_delete(self, comment=None):
|
|
|
|
comment = comment or self.context
|
2022-05-01 23:14:09 +02:00
|
|
|
return len(IReplies(aq_inner(comment))) == 0 and self.could_delete(
|
|
|
|
comment=comment
|
2016-02-05 01:39:53 +01:00
|
|
|
)
|
2012-05-07 13:02:07 +02:00
|
|
|
|
|
|
|
def __call__(self):
|
|
|
|
if self.can_delete():
|
2022-05-01 23:14:41 +02:00
|
|
|
super().__call__()
|
2012-05-07 13:02:07 +02:00
|
|
|
else:
|
2014-09-20 16:02:48 +02:00
|
|
|
raise Unauthorized("You're not allowed to delete this comment.")
|
2012-05-07 13:02:07 +02:00
|
|
|
|
|
|
|
|
2019-12-05 21:55:23 +01:00
|
|
|
class CommentTransition(BrowserView):
|
|
|
|
r"""Publish, reject, recall a comment or mark it as spam.
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 23:02:16 +01:00
|
|
|
This view is always called directly on the comment object:
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 23:02:16 +01:00
|
|
|
http://nohost/front-page/++conversation++default/1286289644723317/\
|
|
|
|
@@transmit-comment
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 23:02:16 +01:00
|
|
|
Each table row (comment) in the moderation view contains a hidden input
|
|
|
|
field with the absolute URL of the content object:
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 23:02:16 +01:00
|
|
|
<input type="hidden"
|
|
|
|
value="http://nohost/front-page/++conversation++default/\
|
|
|
|
1286289644723317"
|
|
|
|
name="selected_obj_paths:list">
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-05 23:02:16 +01:00
|
|
|
This absolute URL is called from a jQuery method that is bind to the
|
|
|
|
'delete' button of the table row. See javascripts/moderation.js for more
|
|
|
|
details.
|
2009-06-26 16:57:45 +02:00
|
|
|
"""
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
def __call__(self):
|
2019-12-05 21:55:23 +01:00
|
|
|
"""Call CommentTransition."""
|
2009-06-26 16:57:45 +02:00
|
|
|
comment = aq_inner(self.context)
|
2011-04-22 19:09:09 +02:00
|
|
|
content_object = aq_parent(aq_parent(comment))
|
2022-05-01 23:14:09 +02:00
|
|
|
workflow_action = self.request.form.get("workflow_action", "publish")
|
|
|
|
workflowTool = getToolByName(self.context, "portal_workflow")
|
2022-04-14 18:29:09 +02:00
|
|
|
workflowTool.doActionFor(comment, workflow_action)
|
2019-12-05 21:55:23 +01:00
|
|
|
comment.reindexObject()
|
2022-05-01 23:14:09 +02:00
|
|
|
content_object.reindexObject(idxs=["total_comments"])
|
2019-12-05 21:55:23 +01:00
|
|
|
notify(CommentPublishedEvent(self.context, comment))
|
2019-12-08 20:01:40 +01:00
|
|
|
# for complexer workflows:
|
|
|
|
notify(CommentTransitionEvent(self.context, comment))
|
2022-05-01 23:14:09 +02:00
|
|
|
comment_state_translated = ""
|
2022-04-14 18:29:09 +02:00
|
|
|
if workflowTool.getWorkflowsFor(comment):
|
2022-05-01 23:14:09 +02:00
|
|
|
review_state_new = workflowTool.getInfoFor(ob=comment, name="review_state")
|
2022-04-14 18:29:09 +02:00
|
|
|
helper = self.context.restrictedTraverse("translationhelper")
|
2022-05-01 23:14:09 +02:00
|
|
|
comment_state_translated = helper.translate_comment_review_state(
|
|
|
|
review_state_new
|
|
|
|
)
|
2019-12-05 21:55:23 +01:00
|
|
|
|
|
|
|
msgid = _(
|
|
|
|
"comment_transmitted",
|
2022-05-01 23:14:09 +02:00
|
|
|
default="Comment ${comment_state_translated}.",
|
|
|
|
mapping={"comment_state_translated": comment_state_translated},
|
|
|
|
)
|
2019-12-05 21:55:23 +01:00
|
|
|
translated = self.context.translate(msgid)
|
2022-05-01 23:14:09 +02:00
|
|
|
IStatusMessage(self.request).add(translated, type="info")
|
2019-12-05 21:55:23 +01:00
|
|
|
|
2011-04-22 19:09:09 +02:00
|
|
|
came_from = self.context.REQUEST.HTTP_REFERER
|
2012-04-12 13:06:05 +02:00
|
|
|
# if the referrer already has a came_from in it, don't redirect back
|
2022-05-01 23:14:09 +02:00
|
|
|
if (
|
|
|
|
len(came_from) == 0
|
|
|
|
or "came_from=" in came_from
|
|
|
|
or not getToolByName(content_object, "portal_url").isURLInPortal(came_from)
|
|
|
|
):
|
2011-04-22 19:09:09 +02:00
|
|
|
came_from = content_object.absolute_url()
|
|
|
|
return self.context.REQUEST.RESPONSE.redirect(came_from)
|
2009-07-07 10:00:41 +02:00
|
|
|
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
class BulkActionsView(BrowserView):
|
2019-12-08 20:01:40 +01:00
|
|
|
"""Call bulk action: publish/approve, delete (, reject, recall, mark as spam).
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-12-16 00:52:56 +01:00
|
|
|
Each table row of the moderation view has a checkbox with the absolute
|
2010-10-05 17:14:12 +02:00
|
|
|
path (without host and port) of the comment objects:
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
<input type="checkbox"
|
|
|
|
name="paths:list"
|
|
|
|
value="/plone/front-page/++conversation++default/\
|
2010-12-16 00:52:56 +01:00
|
|
|
1286289644723317"
|
2010-10-05 17:14:12 +02:00
|
|
|
id="cb_1286289644723317" />
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-12-16 00:52:56 +01:00
|
|
|
If checked, the comment path will occur in the 'paths' variable of
|
|
|
|
the request when the bulk actions view is called. The bulk action
|
|
|
|
(delete, publish, etc.) will be applied to all comments that are
|
2010-10-05 17:14:12 +02:00
|
|
|
included.
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-10-05 17:14:12 +02:00
|
|
|
The paths have to be 'traversable':
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2010-12-16 00:52:56 +01:00
|
|
|
/plone/front-page/++conversation++default/1286289644723317
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
"""
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
def __init__(self, context, request):
|
2022-05-01 23:14:41 +02:00
|
|
|
super().__init__(context, request)
|
2022-05-01 23:14:09 +02:00
|
|
|
self.workflowTool = getToolByName(context, "portal_workflow")
|
2019-12-08 20:01:40 +01:00
|
|
|
|
2009-06-26 16:57:45 +02:00
|
|
|
def __call__(self):
|
2019-12-05 21:55:23 +01:00
|
|
|
"""Call BulkActionsView."""
|
2022-05-01 23:14:09 +02:00
|
|
|
if "form.select.BulkAction" in self.request:
|
|
|
|
bulkaction = self.request.get("form.select.BulkAction")
|
|
|
|
self.paths = self.request.get("paths")
|
2009-06-29 17:09:41 +02:00
|
|
|
if self.paths:
|
2022-05-01 23:14:09 +02:00
|
|
|
if bulkaction == "-1":
|
2009-06-29 17:09:41 +02:00
|
|
|
# no bulk action was selected
|
|
|
|
pass
|
2022-05-01 23:14:09 +02:00
|
|
|
elif bulkaction == "delete":
|
2009-06-29 17:09:41 +02:00
|
|
|
self.delete()
|
|
|
|
else:
|
2019-12-08 20:01:40 +01:00
|
|
|
self.transmit(bulkaction)
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
def transmit(self, action=None):
|
|
|
|
"""Transmit all comments in the paths variable to requested review_state.
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
Expects a list of absolute paths (without host and port):
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
/Plone/startseite/++conversation++default/1286200010610352
|
2010-10-05 17:14:12 +02:00
|
|
|
"""
|
2009-06-26 20:59:37 +02:00
|
|
|
context = aq_inner(self.context)
|
2009-06-29 15:44:46 +02:00
|
|
|
for path in self.paths:
|
2009-06-26 20:59:37 +02:00
|
|
|
comment = context.restrictedTraverse(path)
|
2013-03-28 14:28:22 +01:00
|
|
|
content_object = aq_parent(aq_parent(comment))
|
2019-12-08 20:01:40 +01:00
|
|
|
allowed_transitions = [
|
2022-05-01 23:14:09 +02:00
|
|
|
transition["id"]
|
|
|
|
for transition in self.workflowTool.listActionInfos(object=comment)
|
|
|
|
if transition["category"] == "workflow" and transition["allowed"]
|
|
|
|
]
|
2019-12-08 20:01:40 +01:00
|
|
|
if action in allowed_transitions:
|
|
|
|
self.workflowTool.doActionFor(comment, action)
|
|
|
|
comment.reindexObject()
|
2022-05-01 23:14:09 +02:00
|
|
|
content_object.reindexObject(idxs=["total_comments"])
|
2019-12-08 20:01:40 +01:00
|
|
|
notify(CommentPublishedEvent(content_object, comment))
|
|
|
|
# for complexer workflows:
|
|
|
|
notify(CommentTransitionEvent(self.context, comment))
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2009-06-29 15:44:46 +02:00
|
|
|
def delete(self):
|
2019-12-08 20:01:40 +01:00
|
|
|
"""Delete all comments in the paths variable.
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
Expects a list of absolute paths (without host and port):
|
2012-01-13 10:16:01 +01:00
|
|
|
|
2019-12-08 20:01:40 +01:00
|
|
|
/Plone/startseite/++conversation++default/1286200010610352
|
2010-12-16 00:52:56 +01:00
|
|
|
"""
|
2009-06-26 20:59:37 +02:00
|
|
|
context = aq_inner(self.context)
|
2009-06-29 15:44:46 +02:00
|
|
|
for path in self.paths:
|
2009-06-26 20:59:37 +02:00
|
|
|
comment = context.restrictedTraverse(path)
|
|
|
|
conversation = aq_parent(comment)
|
2013-03-28 14:28:22 +01:00
|
|
|
content_object = aq_parent(conversation)
|
2009-06-26 20:59:37 +02:00
|
|
|
del conversation[comment.id]
|
2022-05-01 23:14:09 +02:00
|
|
|
content_object.reindexObject(idxs=["total_comments"])
|
2018-10-24 16:49:22 +02:00
|
|
|
notify(CommentDeletedEvent(content_object, comment))
|