Author: rspivak
Date: Thu Nov  3 01:39:00 2005
New Revision: 28921

Added:
   z3lab/cpsblog/trunk/comments.py   (contents, props changed)
Modified:
   z3lab/cpsblog/trunk/browser/blogentry.py
   z3lab/cpsblog/trunk/browser/skin/blogentry.pt
   z3lab/cpsblog/trunk/configure.zcml
   z3lab/cpsblog/trunk/interfaces.py
Log:
Initial backend support for comments.

Modified: z3lab/cpsblog/trunk/browser/blogentry.py
==============================================================================
--- z3lab/cpsblog/trunk/browser/blogentry.py    (original)
+++ z3lab/cpsblog/trunk/browser/blogentry.py    Thu Nov  3 01:39:00 2005
@@ -6,7 +6,7 @@
 from zope.app.dublincore.interfaces import IZopeDublinCore
 from zope.app.pagetemplate import ViewPageTemplateFile
 
-from cpsblog.interfaces import IBlogEntry
+from cpsblog.interfaces import IBlogEntry, IComments
 from cpsblog.browser.widgets import FCKEditorWidget
 
 import zope.interface
@@ -60,3 +60,8 @@
 #         for d in absolute_url.breadcrumbs()[:-1]:
 #             result += "<a href='%(url)s'>%(name)s</a>/" % d
 #         return result
+
+    def getComments(self):
+        """Return comments."""
+        comments = IComments(self.context)
+        return comments

Modified: z3lab/cpsblog/trunk/browser/skin/blogentry.pt
==============================================================================
--- z3lab/cpsblog/trunk/browser/skin/blogentry.pt       (original)
+++ z3lab/cpsblog/trunk/browser/skin/blogentry.pt       Thu Nov  3 01:39:00 2005
@@ -12,6 +12,27 @@
       <span tal:content="view/created" />
     </div>
 
+    <div class="blog-entry">
+      <a name="comments">
+      </a>
+      <table width="100%" border="0" cellpadding="0" cellspacing="0">
+        <tr>
+          <td class="blog-footer">
+            <h3>
+              <span tal:replace="python: len(view.getComments())">
+                X
+              </span>
+              Comments:
+            </h3>
+          </td>
+          <td class="blog-footer" align="right">
+            <a href="#" tal:attributes="href string:./comments.html">
+              Post a Comment
+            </a>
+          </td>
+        </tr>
+      </table>
+    </div>
   </div>
 
 </html>
\ No newline at end of file

Added: z3lab/cpsblog/trunk/comments.py
==============================================================================
--- (empty file)
+++ z3lab/cpsblog/trunk/comments.py     Thu Nov  3 01:39:00 2005
@@ -0,0 +1,201 @@
+# $Id$
+from persistent import Persistent
+from persistent.dict import PersistentDict
+
+from zope import interface
+from zope import event
+from zope import component
+
+from zope.app.file import File
+from zope.app.location import Location
+from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
+from zope.app.event.objectevent import Attributes, Sequence
+from zope.app.annotation.interfaces import IAnnotations
+
+from zope.cachedescriptors.property import Lazy
+
+from cpsblog.interfaces import IComment
+from cpsblog.interfaces import IComments, IAttributeAnnotatableComments
+
+
+COMMENTS_KEY = 'cpsblog.comments'
+
+class Comment(File):
+    interface.implements(IComment)
+
+
+class Comments(Location, Persistent):
+    interface.implements(IComments)
+
+    def __init__(self):
+        self.comments = PersistentDict()
+
+    def _get_next_key(self):
+        key = self.__dict__.get('_next_key', 0)
+        self.__dict__['_next_key'] = next_key = key + 1
+        return next_key
+
+    def keys(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        return self.comments.keys()
+
+    def __iter__(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        return self.comments.__iter__()
+
+    def values(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        return self.comments.values()
+
+    def items(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        return self.comments.items()
+
+    def __len__(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        return self.comments.__len__()
+
+    def get(self, key, default=None):
+        "See zope.interface.common.mapping.IReadMapping"
+        return self.comments.get(key, default)
+
+    def __contains__(self, key):
+        "See zope.interface.common.mapping.IReadMapping"
+        return key in self.comments
+
+    def __getitem__(self, key):
+        "See zope.interface.common.mapping.IItemMapping"
+        return self.comments[key]
+
+    def __delitem__(self, key):
+        "See cpsblog.interfaces.IDeleteComments"
+        del self.comments[key]
+
+    def addComment(self, data, contentType='text/plain'):
+        "See cpsblog.interfaces.IAddComments"
+        comment = Comment(data, contentType)
+        event.notify(ObjectCreatedEvent(comment))
+        key = self._get_next_key()
+        self.comments[key] = comment
+        return key
+
+    def editComment(self, key, data, contentType='text/plain'):
+        "See cpsblog.interfaces.IEditComments"
+        comment = self.comments[key]
+
+        changed = ()
+        if comment.data != data:
+            comment.data = data
+            changed += ('data', )
+
+        if comment.contentType != contentType:
+            comment.contentType = contentType
+            changed += ('contentType', )
+
+        if changed:
+            event.notify(ObjectModifiedEvent(comment,
+                                             Attributes(IComment, *changed)))
+        return chnaged
+
+
+class AnnotatableComments(Location):
+    component.adapts(IAttributeAnnotatableComments)
+    interface.implements(IComments)
+
+    def __init__(self, context):
+        self.context = context
+
+    def _get_comments(self):
+        _dict = self.__dict__
+        annotations = _dict.get('_annotations')
+        if annotations is None:
+            _dict['_annotations'] = annotations = IAnnotations(self.context)
+        return annotations.get(COMMENTS_KEY, None)
+
+    comments = Lazy(_get_comments)
+
+    def _clear_comments_attr(self):
+        try:
+            del self.comments
+        except AttributeError:
+            pass
+
+    def keys(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        if self.comments is not None:
+            return self.comments.keys()
+        else:
+            return []
+
+    def __iter__(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        if self.comments is not None:
+            return self.comments.__iter__()
+        else:
+            return __iter__([])
+
+    def values(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        if self.comments is not None:
+            return self.comments.values()
+        else:
+            return []
+
+    def items(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        if self.comments is not None:
+            return self.comments.items()
+        else:
+            return []
+
+    def __len__(self):
+        "See zope.interface.common.mapping.IEnumerableMapping"
+        if self.comments is not None:
+            return self.comments.__len__()
+        else:
+            return 0
+
+    def get(self, key, default=None):
+        "See zope.interface.common.mapping.IReadMapping"
+        if self.comments is not None:
+            return self.comments.get(key, default)
+        else:
+            return default
+
+    def __contains__(self, key):
+        "See zope.interface.common.mapping.IReadMapping"
+        if self.comments is not None:
+            return key in self.comments
+        else:
+            return False
+
+    def __getitem__(self, key):
+        "See zope.interface.common.mapping.IItemMapping"
+        return self.comments[key]
+
+    def __delitem__(self, key):
+        "See cpsblog.interfaces.IDeleteComments"
+        del self.comments[key]
+        self._clear_comments_attr()
+        event.notify(ObjectModifiedEvent(self.context, Attributes(IComments)))
+
+    def addComment(self, data, contentType='text/plain'):
+        "See cpsblog.interfaces.IAddComments"
+        if self.comments is None:
+            self.__dict__['_annotations'][COMMENTS_KEY] = Comments()
+        key = self.comments.addComment(data, contentType)
+        self._clear_comments_attr()
+        evt_obj = ObjectModifiedEvent(self.context, Sequence(IComments, key))
+        event.notify(evt_obj)
+        return key
+
+    def editComment(self, key, data, contentType='text/plain'):
+        "See cpsblog.interfaces.IEditComments"
+        if self.comments is not None:
+            changed = self.comments.editComment(key, data, contentType)
+            self._clear_comments_attr()
+            context = self.context
+            event.notify(ObjectModifiedEvent(context, Sequence(IComments, 
key)))
+            return changed
+        else:
+            raise KeyError(key)

Modified: z3lab/cpsblog/trunk/configure.zcml
==============================================================================
--- z3lab/cpsblog/trunk/configure.zcml  (original)
+++ z3lab/cpsblog/trunk/configure.zcml  Thu Nov  3 01:39:00 2005
@@ -91,6 +91,9 @@
     <implements
        interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
        />
+    <implements
+        interface="cpsblog.interfaces.IAttributeAnnotatableComments"
+        />
     <factory
        id="blogentry.BlogEntry"
        description="Blog Entry"
@@ -155,6 +158,47 @@
         />
   </content>
 
+
+  <!-- Comment -->
+  <content class=".comments.Comment">
+    <factory id="comment.interfaces.IComment" />
+    <implements
+        interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
+        />
+    <require
+        permission="zope.Public"
+        interface=".interfaces.IComment"
+        />
+    <require
+        permission="zope.ManageContent"
+        set_schema=".interfaces.IComment"
+        />
+  </content>
+
+
+  <!-- Comments -->
+  <class class=".comments.AnnotatableComments">
+    <factory id="comment.interfaces.IComments" />
+    <require
+        permission="zope.Public"
+        interface=".interfaces.IReadComments"
+        />
+    <require
+        permission="zope.View"
+        interface=".interfaces.IDeleteComments"
+        />
+    <require
+        permission="zope.ManageContent"
+        set_schema=".interfaces.IComment"
+        />
+  </class>
+
+  <adapter
+      provides=".interfaces.IComments"
+      factory=".comments.AnnotatableComments"
+      trusted="True" />
+
+
   <subscriber
       for="zope.app.container.interfaces.IObjectAddedEvent"
       handler=".blogportal.setupSiteManager"

Modified: z3lab/cpsblog/trunk/interfaces.py
==============================================================================
--- z3lab/cpsblog/trunk/interfaces.py   (original)
+++ z3lab/cpsblog/trunk/interfaces.py   Thu Nov  3 01:39:00 2005
@@ -1,6 +1,8 @@
 # $Id$
 from zope.interface import Interface, Attribute
 from zope.schema import Text, TextLine, Field, Choice, List
+from zope.interface.common.mapping import IEnumerableMapping
+from zope.app.annotation.interfaces import IAttributeAnnotatable
 
 from zope.app.container.constraints import ContainerTypesConstraint
 from zope.app.container.constraints import ItemTypePrecondition
@@ -8,7 +10,7 @@
 from zope.app.container.interfaces import IContained, IContainer
 from zope.app.authentication.principalfolder import IInternalPrincipalContainer
 
-from zope.app.file.interfaces import IImage
+from zope.app.file.interfaces import IImage, IFile
 
 class IBlogEntry(Interface):
     """Interface for blog entry objects."""
@@ -130,3 +132,37 @@
 
 class IPortrait(IImage):
     """Holds portrait image of member."""
+
+
+# Comments
+
+class IComment(IFile):
+    """ """
+
+class IReadComments(IEnumerableMapping):
+    """Read comments from comments collection."""
+
+class IDeleteComments(Interface):
+    """Remove comment from comments collection."""
+    def __delitem__(key):
+        """ """
+
+class IAddComments(Interface):
+    def addComment(data, contentType='text/plain'):
+        """Add comment to collection.
+
+        Return key of newly added comment.
+        """
+
+class IEditComments(Interface):
+    def editComment(key, data, contentType='text/plain'):
+        """Edit comment from collection.
+
+        Return changed attributes.
+        """
+
+class IComments(IReadComments, IDeleteComments, IAddComments, IEditComments):
+    """Collection of comments."""
+
+class IAttributeAnnotatableComments(IAttributeAnnotatable):
+    """Marker interface"""
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to