Moved 'review' code to 'features' module
authorThierry Florac <thierry.florac@onf.fr>
Fri, 10 Nov 2017 12:05:25 +0100
changeset 272 c8e9ace0bf35
parent 271 d88bd7cdaebf
child 273 d70e47b99ffb
Moved 'review' code to 'features' module
src/pyams_content/shared/common/review.py
--- a/src/pyams_content/shared/common/review.py	Fri Nov 10 12:04:50 2017 +0100
+++ b/src/pyams_content/shared/common/review.py	Fri Nov 10 12:05:25 2017 +0100
@@ -14,220 +14,10 @@
 
 
 # import standard library
-import os
-from datetime import datetime
-from uuid import uuid4
 
 # import interfaces
-from pyams_content.interfaces import READER_ROLE
-from pyams_content.interfaces.review import IReviewManager, IReviewComment, IReviewComments, \
-    REVIEW_COMMENTS_ANNOTATION_KEY, CommentAddedEvent, ICommentAddedEvent
-from pyams_content.shared.common.interfaces import IWfSharedContent, IWfSharedContentRoles
-from pyams_i18n.interfaces import II18n
-from pyams_mail.interfaces import IPrincipalMailInfo
-from pyams_security.interfaces import ISecurityManager, IProtectedObject
-from pyams_security.interfaces.notification import INotificationSettings
-from pyramid_chameleon.interfaces import IChameleonTranslate
-from pyramid_mailer.interfaces import IMailer
-from zope.annotation.interfaces import IAnnotations
-from zope.location.interfaces import ISublocations
-from zope.traversing.interfaces import ITraversable
 
 # import packages
-from persistent import Persistent
-from pyams_mail.message import HTMLMessage
-from pyams_security.principal import MissingPrincipal
-from pyams_utils.adapter import adapter_config, ContextAdapter
-from pyams_utils.container import BTreeOrderedContainer
-from pyams_utils.registry import query_utility
-from pyams_utils.request import check_request, query_request
-from pyams_utils.url import absolute_url
-from pyramid.events import subscriber
-from pyramid.threadlocal import get_current_registry
-from pyramid_chameleon.zpt import PageTemplateFile
-from zope.container.contained import Contained
-from zope.interface import implementer
-from zope.location import locate
-from zope.schema.fieldproperty import FieldProperty
 
-from pyams_content import _
-
-
-@implementer(IReviewComment)
-class ReviewComment(Persistent, Contained):
-    """Review comment persistent class"""
-
-    owner = FieldProperty(IReviewComment['owner'])
-    comment = FieldProperty(IReviewComment['comment'])
-    comment_type = FieldProperty(IReviewComment['comment_type'])
-    creation_date = FieldProperty(IReviewComment['creation_date'])
-
-    def __init__(self, owner, comment, comment_type='comment'):
-        self.owner = owner
-        self.comment = comment
-        self.comment_type = comment_type
-        self.creation_date = datetime.utcnow()
-
-
-@implementer(IReviewComments)
-class ReviewCommentsContainer(BTreeOrderedContainer):
-    """Review comments container"""
-
-    reviewers = FieldProperty(IReviewComments['reviewers'])
-
-    def clear(self):
-        for k in self.keys()[:]:
-            del self[k]
-
-    def add_comment(self, comment):
-        uuid = str(uuid4())
-        self[uuid] = comment
-        reviewers = self.reviewers or set()
-        reviewers.add(comment.owner)
-        self.reviewers = reviewers
-        get_current_registry().notify(CommentAddedEvent(self.__parent__, comment))
-
-
-@adapter_config(context=IWfSharedContent, provides=IReviewComments)
-def SharedContentReviewCommentsFactory(context):
-    """Shared content review comments factory"""
-    annotations = IAnnotations(context)
-    comments = annotations.get(REVIEW_COMMENTS_ANNOTATION_KEY)
-    if comments is None:
-        comments = annotations[REVIEW_COMMENTS_ANNOTATION_KEY] = ReviewCommentsContainer()
-        locate(comments, context, '++review-comments++')
-    return comments
-
-
-@adapter_config(name='review-comments', context=IWfSharedContent, provides=ITraversable)
-class SharedContentReviewCommentsNamespace(ContextAdapter):
-    """++review-comments++ namespace traverser"""
-
-    def traverse(self, name, furtherpath=None):
-        return IReviewComments(self.context)
-
-
-@adapter_config(name='review-comments', context=IWfSharedContent, provides=ISublocations)
-class SharedContentReviewCommentsSublocations(ContextAdapter):
-    """Shared content review comments sub-location adapter"""
-
-    def sublocations(self):
-        return IReviewComments(self.context).values()
-
-
-@adapter_config(context=IWfSharedContent, provides=IReviewManager)
-class SharedContentReviewAdapter(ContextAdapter):
-    """Shared content review adapter"""
-
-    review_template = PageTemplateFile(os.path.join(os.path.dirname(__file__),
-                                                    'zmi/templates/review-notification.pt'))
-
-    def ask_review(self, reviewers, comment, notify_all=True):
-        """Ask for content review"""
-        roles = IWfSharedContentRoles(self.context, None)
-        if roles is None:
-            return
-        # check request
-        request = check_request()
-        translate = request.localizer.translate
-        # initialize mailer
-        security = query_utility(ISecurityManager)
-        settings = INotificationSettings(security)
-        sender_name = request.principal.title if request.principal is not None else settings.sender_name
-        sender_address = settings.sender_email
-        sender = security.get_principal(request.principal.id, info=False)
-        sender_mail_info = IPrincipalMailInfo(sender, None)
-        if sender_mail_info is not None:
-            for sender_name, sender_address in sender_mail_info.get_addresses():
-                break
-        if settings.enable_notifications:
-            mailer = query_utility(IMailer, name=settings.mailer)
-        else:
-            mailer = None
-        # create message
-        message_body = self.review_template(request=request,
-                                            context=self.context,
-                                            translate=query_utility(IChameleonTranslate),
-                                            options={'settings': settings,
-                                                     'comment': comment,
-                                                     'sender': sender_name})
-        # notify reviewers
-        notifications = 0
-        readers = roles.readers
-        for reviewer in reviewers:
-            if settings.enable_notifications and \
-                    (mailer is not None) and \
-                    (notify_all or (reviewer not in readers)):
-                principal = security.get_principal(reviewer, info=False)
-                if not isinstance(principal, MissingPrincipal):
-                    mail_info = IPrincipalMailInfo(principal, None)
-                    if mail_info is not None:
-                        for name, address in mail_info.get_addresses():
-                            message = HTMLMessage(
-                                subject=translate(_("[{service_name}] A content review is requested")).format(
-                                    service_name=settings.subject_prefix),
-                                fromaddr='{name} <{address}>'.format(name=sender_name,
-                                                                     address=sender_address),
-                                toaddr='{name} <{address}>'.format(name=name, address=address),
-                                html=message_body)
-                            mailer.send(message)
-                            notifications += 1
-            readers.add(reviewer)
-        roles.readers = readers
-        # add comment
-        review_comment = ReviewComment(owner=request.principal.id,
-                                       comment=comment,
-                                       comment_type='request')
-        IReviewComments(self.context).add_comment(review_comment)
-        # return notifications count
-        return notifications
-
-
-#
-# Review comment notification
-#
-
-try:
-    from pyams_notify.interfaces import INotification, INotificationHandler
-    from pyams_notify.event import Notification
-except ImportError:
-    pass
-else:
-
-    @subscriber(ICommentAddedEvent)
-    def handle_new_comment(event):
-        """Handle new review comment"""
-        request = query_request()
-        if request is None:
-            return
-        content = event.object
-        translate = request.localizer.translate
-        notification = Notification(request=request,
-                                    context=content,
-                                    source=event.comment.owner,
-                                    action='notify',
-                                    category='content.review',
-                                    message=translate(_("A new comment was added on content « {0} »")).format(
-                                        II18n(content).query_attribute('title', request=request)),
-                                    url=absolute_url(content, request, 'admin#review-comments.html'),
-                                    comments=IReviewComments(content))
-        notification.send()
-
-
-    @adapter_config(name='content.review', context=INotification, provides=INotificationHandler)
-    class ContentReviewNotificationHandler(ContextAdapter):
-        """Content review notification handler"""
-
-        def get_target(self):
-            context = self.context.context
-            principals = set()
-            protection = IProtectedObject(context, None)
-            if protection is not None:
-                principals |= protection.get_principals(READER_ROLE)
-            comments = self.context.user_data.get('comments')
-            if comments is not None:
-                principals |= comments.reviewers
-            source_id = self.context.source['id']
-            if source_id in principals:
-                principals.remove(source_id)
-            return {'principals': tuple(principals)}
+# imports for backward compatibility: module moved to pyams_content.features.review !!
+from pyams_content.features.review import ReviewComment, ReviewCommentsContainer