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,6 +29,9 @@ 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)

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
self._creator2id = OOBTree() # To search/order on creator ids
def index(self, comment): def reindexObject(self, object):
# Store the object in the store: """Remove from catalog.
id = comment.comment_id """
self._id2uid[id] = comment.__parent__._parent_uid catalog = getToolByName(self, 'portal_catalog')
self._id2text[id] = comment.text return catalog.reindexObject(object)
# TODO indexObject = reindexObject
## Index on workflow state
#wfstate = comment.getWorkflowState()
#if not wfstate in self._wfstate2id:
#self._wfstate2id[wfstate] = OOSet()
#self._wfstate2id[wfstate].insert(id)
# Index on creator def unindexObject(self, object):
creator = comment.creator """Remove from catalog.
if not creator in self._creator2id: """
self._creator2id[creator] = OOSet() catalog = getToolByName(self, 'portal_catalog')
self._creator2id[creator].insert(id) return catalog.unindexObject(object)
def search(self, creator=None): def uniqueValuesFor(self, name):
if creator is not None: """ return unique values for FieldIndex name """
# Get all replies for a certain object catalog = getToolByName(self, 'portal_catalog')
ids = self._creator2ids.get(creator, None) return catalog.uniqueValuesFor(name)
if ids is None:
raise StopIteration def searchResults(self, REQUEST=None, **kw):
"""
Calls ZCatalog.searchResults with extra arguments that
limit the results to what the user is allowed to see.
"""
catalog = getToolByName(self, 'portal_catalog')
object_provides = [IComment.__identifier__]
if 'object_provides' in kw:
kw_provides = kw['object_provides']
if isinstance(str, kw_provides):
object_provides.append(kw_provides)
else: else:
ids = self._id2uid.keys() object_provides.extend(kw_provides)
if REQUEST is not None and 'object_provides' in REQUEST.form:
for id in ids: rq_provides = REQUEST.form['object_provides']
yield {'id': id, del REQUEST.form['object_provides']
'text': self._id2text[id] if isinstance(str, rq_provides):
# TODO: More data + maybe brains or something? object_provides.append(rq_provides)
} 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)