Trigger custom comment events on comment add/remove/reply

Conflicts:
	plone/app/discussion/interfaces.py
This commit is contained in:
Alin Voinea 2014-04-16 18:54:19 +03:00
parent 5a9bfdf876
commit 4343197209
7 changed files with 450 additions and 1 deletions

View File

@ -10,6 +10,7 @@ from smtplib import SMTPException
from zope.annotation.interfaces import IAnnotatable
from zope.event import notify
from zope.component.factory import Factory
from zope.component import queryUtility
@ -32,6 +33,11 @@ from OFS.Traversable import Traversable
from plone.registry.interfaces import IRegistry
from plone.app.discussion.events import CommentAddedEvent
from plone.app.discussion.events import CommentRemovedEvent
from plone.app.discussion.events import ReplyAddedEvent
from plone.app.discussion.events import ReplyRemovedEvent
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IConversation
@ -232,7 +238,6 @@ def notify_content_object(obj, event):
'last_comment_date',
'commentators'))
def notify_content_object_deleted(obj, event):
"""Remove all comments of a content object when the content object has been
deleted.
@ -242,6 +247,19 @@ def notify_content_object_deleted(obj, event):
while conversation:
del conversation[conversation.keys()[0]]
def notify_comment_added(obj, event):
""" Notify custom discussion events when a comment is added or replied
"""
if getattr(obj, 'in_reply_to', None):
return notify(ReplyAddedEvent(obj))
return notify(CommentAddedEvent(obj))
def notify_comment_removed(obj, event):
""" Notify custom discussion events when a comment or reply is removed
"""
if getattr(obj, 'in_reply_to', None):
return notify(ReplyRemovedEvent(obj))
return notify(CommentRemovedEvent(obj))
def notify_content_object_moved(obj, event):
"""Update all comments of a content object that has been moved.

View File

@ -14,6 +14,7 @@
<include package="plone.uuid" />
<include package="plone.app.uuid" />
<include file="contentrules.zcml" />
<include file="permissions.zcml" />
<include file="notifications.zcml" />
<include file="subscribers.zcml" />

View File

@ -0,0 +1,42 @@
""" Content rules handlers
"""
from Acquisition import aq_parent
from plone.app.contentrules.handlers import execute
from plone.stringinterp import adapters
def execute_comment(event):
""" Execute comment content rules
"""
execute(event.object, event)
#
# String interp for comment's content rules
#
class Mixin(object):
""" Override context
"""
@property
def context(self):
""" Getter
"""
conversation = aq_parent(self._context)
return aq_parent(conversation)
@context.setter
def context(self, value):
""" Setter
"""
self._context = value
class CommentUrlSubstitution(adapters.UrlSubstitution, Mixin):
""" Override context to be used for URL substitution
"""
class CommentParentUrlSubstitution(adapters.ParentUrlSubstitution, Mixin):
""" Override context to be used for Parent URL substitution
"""
class CommentIdSubstitution(adapters.IdSubstitution, Mixin):
""" Override context to be used for Id substitution
"""

View File

@ -0,0 +1,313 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:zcml="http://namespaces.zope.org/zcml">
<configure zcml:condition="installed plone.contentrules">
<!-- Content Rules events -->
<interface
interface="plone.app.discussion.interfaces.ICommentAddedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment added"
/>
<interface
interface="plone.app.discussion.interfaces.ICommentRemovedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment removed"
/>
<interface
interface="plone.app.discussion.interfaces.IReplyAddedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment reply added"
/>
<interface
interface="plone.app.discussion.interfaces.IReplyRemovedEvent"
type="plone.contentrules.rule.interfaces.IRuleEventType"
name="Comment reply removed"
/>
</configure>
<configure zcml:condition="installed plone.app.contentrules">
<!-- Content rules subscribers -->
<subscriber
for="plone.app.discussion.interfaces.ICommentAddedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.ICommentRemovedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.IReplyAddedEvent"
handler=".contentrules.execute_comment"
/>
<subscriber
for="plone.app.discussion.interfaces.IReplyRemovedEvent"
handler=".contentrules.execute_comment"
/>
<!-- Content rules string substitutions -->
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentUrlSubstitution"
name="absolute_url"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentUrlSubstitution"
name="url"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentParentUrlSubstitution"
name="parent_url"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentIdSubstitution"
name="id"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentTitleSubstitution"
name="title"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentParentTitleSubstitution"
name="parent_title"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentDescriptionSubstitution"
name="description"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentTypeSubstitution"
name="type"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentReviewStateSubstitution"
name="review_state"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentReviewStateTitleSubstitution"
name="review_state_title"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentCreatedSubstitution"
name="created"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentEffectiveSubstitution"
name="effective"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentExpiresSubstitution"
name="expires"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentModifiedSubstitution"
name="modified"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentCreatorsSubstitution"
name="creators"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentContributorsSubstitution"
name="contributors"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentSubjectSubstitution"
name="subject"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentSubjectSubstitution"
name="keywords"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentFormatSubstitution"
name="format"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentLanguageSubstitution"
name="language"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentRightsSubstitution"
name="rights"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentIdentifierSubstitution"
name="identifier"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentOwnerEmailSubstitution"
name="owner_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentReviewerEmailSubstitution"
name="reviewer_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentReaderEmailSubstitution"
name="reader_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentEditorEmailSubstitution"
name="editor_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentContributorEmailSubstitution"
name="contributor_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentManagerEmailSubstitution"
name="manager_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentMemberEmailSubstitution"
name="member_emails"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentUserEmailSubstitution"
name="user_email"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentUserFullNameSubstitution"
name="user_fullname"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentUserIdSubstitution"
name="user_id"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentLastChangeCommentSubstitution"
name="change_comment"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentLastChangeTitleSubstitution"
name="change_title"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentLastChangeTypeSubstitution"
name="change_type"
/>
<adapter
for="plone.app.discussion.interfaces.IComment"
provides="plone.stringinterp.interfaces.IStringSubstitution"
factory=".contentrules.CommentLastChangeActorIdSubstitution"
name="change_authorid"
/>
</configure>
</configure>

View File

@ -0,0 +1,38 @@
""" Custom discussion events
"""
from zope.interface import implements
from plone.app.discussion.interfaces import IDiscussionEvent
from plone.app.discussion.interfaces import ICommentAddedEvent
from plone.app.discussion.interfaces import ICommentRemovedEvent
from plone.app.discussion.interfaces import IReplyAddedEvent
from plone.app.discussion.interfaces import IReplyRemovedEvent
class DiscussionEvent(object):
""" Custom event
"""
implements(IDiscussionEvent)
def __init__(self, context, **kwargs):
self.object = context
for key, value in kwargs.items():
setattr(self, key, value)
class CommentAddedEvent(DiscussionEvent):
""" Event to be triggered when a Comment is added
"""
implements(ICommentAddedEvent)
class CommentRemovedEvent(DiscussionEvent):
""" Event to be triggered when a Comment is removed
"""
implements(ICommentRemovedEvent)
class ReplyAddedEvent(DiscussionEvent):
""" Event to be triggered when a Comment reply is added
"""
implements(IReplyAddedEvent)
class ReplyRemovedEvent(DiscussionEvent):
""" Event to be triggered when a Comment reply is removed
"""
implements(IReplyRemovedEvent)

View File

@ -4,6 +4,7 @@
from zope.interface import Interface
from zope.interface.common.mapping import IIterableMapping
from zope.component.interfaces import IObjectEvent
from zope import schema
from plone.app.discussion import PloneAppDiscussionMessageFactory as _
@ -345,3 +346,27 @@ class ICommentingTool(Interface):
This can be removed once we no longer support upgrading from versions
of Plone that had a portal_discussion tool.
"""
#
# Custom events
#
class IDiscussionEvent(IObjectEvent):
""" Discussion custom event
"""
class ICommentAddedEvent(IDiscussionEvent):
""" Comment added
"""
class ICommentRemovedEvent(IDiscussionEvent):
""" Comment removed
"""
class IReplyAddedEvent(IDiscussionEvent):
""" Comment reply added
"""
class IReplyRemovedEvent(IDiscussionEvent):
""" Comment reply removed
"""

View File

@ -15,12 +15,24 @@
handler=".comment.notify_content_object"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectAddedEvent"
handler=".comment.notify_comment_added"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectRemovedEvent"
handler=".comment.notify_content_object"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectRemovedEvent"
handler=".comment.notify_comment_removed"
/>
<subscriber
for="plone.app.discussion.interfaces.IComment
zope.lifecycleevent.interfaces.IObjectAddedEvent"