Moved the indexing to be a catalog wrapper.

svn path=/plone.app.discussion/trunk/; revision=27005
This commit is contained in:
Lennart Regebro 2009-05-17 18:38:45 +00:00
parent e35f761939
commit acf00c9de9
6 changed files with 73 additions and 48 deletions

View File

@ -115,7 +115,9 @@ class Conversation(Persistent, Explicit):
if not reply_to in self._children: if not reply_to in self._children:
self._children[reply_to] = LLSet() self._children[reply_to] = LLSet()
self._children[reply_to].insert(id) self._children[reply_to].insert(id)
notify(ObjectAddedEvent(comment, self, id)) # Notify that the object is added. The object must here be
# acquisition wrapped or the indexing will fail.
notify(ObjectAddedEvent(comment.__of__(self), self, id))
notify(ContainerModifiedEvent(self)) notify(ContainerModifiedEvent(self))
# Dict API # Dict API
@ -137,6 +139,9 @@ class Conversation(Persistent, Explicit):
def keys(self): def keys(self):
return self._comments.keys() return self._comments.keys()
def getPhysicalPath(self):
return self.aq_parent.getPhysicalPath() + (self.id,)
# TODO: Update internal data structures when items added or removed # TODO: Update internal data structures when items added or removed
@implementer(IConversation) @implementer(IConversation)

View File

@ -3,7 +3,7 @@
<utilities> <utilities>
<utility <utility
interface="plone.app.discussion.interfaces.ICommentingTool" interface="plone.app.discussion.interfaces.ICommentingTool"
factory="plone.app.discussion.tool.CommentingTool" object="portal_discussion"
/> />
</utilities> </utilities>
</componentregistry> </componentregistry>

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<tool-setup>
<required tool_id="portal_discussion"
class="plone.app.discussion.tool.CommentingTool"/>
</tool-setup>

View File

@ -29,7 +29,10 @@ class ConversationTest(TestCase):
# Create a conversation. In this case we doesn't assign it to an # Create a conversation. In this case we doesn't assign it to an
# object, as we just want to check the Conversation object API. # object, as we just want to check the Conversation object API.
conversation = IConversation(self.portal.doc1) conversation = IConversation(self.portal.doc1)
# Pretend that we have traversed to the comment by aq wrapping it.
# XXX implement traversal to commenting and change this:
conversation = conversation.__of__(self.portal.doc1)
# Add a comment. reply_to=0 means it's not a reply # Add a comment. reply_to=0 means it's not a reply
comment = Comment(conversation=conversation, reply_to=0) comment = Comment(conversation=conversation, reply_to=0)
comment.title = 'Comment 1' comment.title = 'Comment 1'

View File

@ -29,6 +29,9 @@ class ToolTest(TestCase):
# Create a conversation. In this case we doesn't assign it to an # Create a conversation. In this case we doesn't assign it to an
# object, as we just want to check the Conversation object API. # object, as we just want to check the Conversation object API.
conversation = IConversation(self.portal.doc1) conversation = IConversation(self.portal.doc1)
# Pretend that we have traversed to the comment by aq wrapping it.
# XXX implement traversal to commenting and change this:
conversation = conversation.__of__(self.portal.doc1)
# Add a comment. reply_to=0 means it's not a reply # Add a comment. reply_to=0 means it's not a reply
comment = Comment(conversation=conversation, reply_to=0) comment = Comment(conversation=conversation, reply_to=0)
@ -39,8 +42,10 @@ class ToolTest(TestCase):
# Check that the comment got indexed in the tool: # Check that the comment got indexed in the tool:
tool = getUtility(ICommentingTool) tool = getUtility(ICommentingTool)
comment = list(tool.search())[0] comment = list(tool.searchResults())
self.assertEquals(comment['text'], 'Comment text') self.assert_(len(comment) == 1, "There is only one comment, but we got"
" %s results in the search" % len(comment))
self.assertEquals(comment[0].Title, 'Comment 1')
def test_suite(): def test_suite():

View File

@ -2,58 +2,65 @@ import time
from zope import interface from zope import interface
from zope.component import getUtility from zope.component import getUtility
from BTrees.OOBTree import OOBTree, OOSet, intersection from interfaces import ICommentingTool, IComment
from interfaces import ICommentingTool
# The commenting tool, which is a local utility # The commenting tool, which is a local utility
class CommentingTool(object): from Products.CMFCore.utils import UniqueObject, getToolByName
from OFS.SimpleItem import SimpleItem
class CommentingTool(UniqueObject, SimpleItem):
interface.implements(ICommentingTool) interface.implements(ICommentingTool)
def __init__(self): meta_type = 'plone.app.discussion tool'
self._id2uid = OOBTree() # The comment ID to object UID id = 'portal_discussion'
self._id2text = OOBTree() # The text for a comment
self._wfstate2id = OOBTree() # To search on wf states def reindexObject(self, object):
self._creator2id = OOBTree() # To search/order on creator ids """Remove from catalog.
"""
def index(self, comment): catalog = getToolByName(self, 'portal_catalog')
# Store the object in the store: return catalog.reindexObject(object)
id = comment.comment_id
self._id2uid[id] = comment.__parent__._parent_uid indexObject = reindexObject
self._id2text[id] = comment.text
# TODO def unindexObject(self, object):
## Index on workflow state """Remove from catalog.
#wfstate = comment.getWorkflowState() """
#if not wfstate in self._wfstate2id: catalog = getToolByName(self, 'portal_catalog')
#self._wfstate2id[wfstate] = OOSet() return catalog.unindexObject(object)
#self._wfstate2id[wfstate].insert(id)
def uniqueValuesFor(self, name):
""" return unique values for FieldIndex name """
catalog = getToolByName(self, 'portal_catalog')
return catalog.uniqueValuesFor(name)
# Index on creator def searchResults(self, REQUEST=None, **kw):
creator = comment.creator """
if not creator in self._creator2id: Calls ZCatalog.searchResults with extra arguments that
self._creator2id[creator] = OOSet() limit the results to what the user is allowed to see.
self._creator2id[creator].insert(id) """
catalog = getToolByName(self, 'portal_catalog')
def search(self, creator=None): object_provides = [IComment.__identifier__]
if creator is not None: if 'object_provides' in kw:
# Get all replies for a certain object kw_provides = kw['object_provides']
ids = self._creator2ids.get(creator, None) if isinstance(str, kw_provides):
if ids is None: object_provides.append(kw_provides)
raise StopIteration else:
else: object_provides.extend(kw_provides)
ids = self._id2uid.keys() if REQUEST is not None and 'object_provides' in REQUEST.form:
rq_provides = REQUEST.form['object_provides']
for id in ids: del REQUEST.form['object_provides']
yield {'id': id, if isinstance(str, rq_provides):
'text': self._id2text[id] object_provides.append(rq_provides)
# TODO: More data + maybe brains or something? else:
} object_provides.extend(rq_provides)
kw['object_provides'] = object_provides
return catalog.searchResults(REQUEST, **kw)
def object_added_handler(obj, event): def object_added_handler(obj, event):
tool = getUtility(ICommentingTool) tool = getUtility(ICommentingTool)
tool.index(obj) tool.indexObject(obj)
def object_removed_handler(obj, event): def object_removed_handler(obj, event):
tool = getUtility(ICommentingTool) tool = getUtility(ICommentingTool)
tool.unindex(obj) tool.unindexObject(obj)