diff --git a/plone/app/discussion/conversation.py b/plone/app/discussion/conversation.py index 11eebaf..866c838 100644 --- a/plone/app/discussion/conversation.py +++ b/plone/app/discussion/conversation.py @@ -106,26 +106,42 @@ class Conversation(Traversable, Persistent, Explicit): if IFolderish.providedBy(aq_inner(self.__parent__)) and not INonStructuralFolder.providedBy(aq_inner(self.__parent__)): return False - # Check folders by traversing through the object tree - allowed = False - def traverse(obj): - # Run from context to the Plone Site Root + # Traverse the object tree. + def traverse_parent_folder(obj): + # Run through the object tree from context, + # to the Plone Site Root and look for the first folder object + # that has allow_discussion set to True or False. if not IPloneSiteRoot.providedBy(obj): - # Look for Plone folders - if IFolderish.providedBy(obj) and not INonStructuralFolder.providedBy(obj): - if portal_discussion.isDiscussionAllowedFor(obj): - #print "FOLDER %s: discussion allowed => override" % obj.id - allowed = True - traverse(aq_parent(obj)) + if IFolderish.providedBy(obj) and \ + not INonStructuralFolder.providedBy(obj): + # If the current object is a Plone folder, + # check if the discussion_allowed flag is set. + allow_discussion_flag = getattr(obj, 'allow_discussion', None) + if allow_discussion_flag == True: + return True + elif allow_discussion_flag == False: + return False + else: + # If allow_discussion flag is not set, go on traversing. + pass + else: + # If the current object is not a Plone folder, + # go on with traversal. + foo = traverse_parent_folder(aq_parent(obj)) + if foo: + return True obj = aq_parent(self) - #print "" - #print "### START TRAVERSE ###" - # Start traversing - #traverse(obj) - #print allowed - #print "### END TRAVERSE ###" + # Check if traversal returned a folder with discussion_allowed set + # to True or False. + folder_allow_discussion = traverse_parent_folder(obj) + if folder_allow_discussion == True: + if not getattr(self, 'allow_discussion', None): + return True + elif folder_allow_discussion == False: + if getattr(aq_inner(self.__parent__), 'allow_discussion', None): + return True # Check if discussion is allowed on the content type portal_type = self.__parent__.portal_type @@ -133,8 +149,7 @@ class Conversation(Traversable, Persistent, Explicit): if not document_fti.getProperty('allow_discussion'): # If discussion is not allowed on the content type, # check if 'allow discussion' is overridden on the content object. - #if hasattr( aq_base(self.__parent__), 'allow_discussion' ): - if not portal_discussion.isDiscussionAllowedFor(aq_inner(self.__parent__)): + if not getattr(aq_inner(self.__parent__), 'allow_discussion', None): return False return True diff --git a/plone/app/discussion/tests/test_conversation.py b/plone/app/discussion/tests/test_conversation.py index adf08d6..b8c1a3e 100644 --- a/plone/app/discussion/tests/test_conversation.py +++ b/plone/app/discussion/tests/test_conversation.py @@ -152,6 +152,10 @@ class ConversationTest(PloneTestCase): # allow discussion attribute. Maybe we should remove this at # some point. + # 1) allow_discussion attribute: Every content object in Plone + # has a allow_discussion attribute. By default it is set to None. + + # Create a conversation. conversation = IConversation(self.portal.doc1) @@ -167,8 +171,11 @@ class ConversationTest(PloneTestCase): # By default, allow_discussion on newly created content objects is # set to False portal_discussion = getToolByName(self.portal, 'portal_discussion') - self.failIf(portal_discussion.isDiscussionAllowedFor(self.portal.doc1)) - self.failIf(self.portal.doc1.getTypeInfo().allowDiscussion()) + self.assertEquals(portal_discussion.isDiscussionAllowedFor(self.portal.doc1), False) + self.assertEquals(self.portal.doc1.getTypeInfo().allowDiscussion(), False) + + # The allow discussion flag is None by default + self.failIf(getattr(self.portal.doc1, 'allow_discussion', None)) # But isDiscussionAllowedFor, also checks if discussion is allowed on the # content type. So we allow discussion on the Document content type and @@ -182,16 +189,19 @@ class ConversationTest(PloneTestCase): self.portal_discussion.overrideDiscussionFor(self.portal.doc1, False) # Check if the Document discussion is disabled self.assertEquals(portal_discussion.isDiscussionAllowedFor(self.portal.doc1), False) + # Check that the local allow_discussion flag is now explicitly set to False + self.assertEquals(getattr(self.portal.doc1, 'allow_discussion', None), False) # Disallow discussion on the Document content type again document_fti.manage_changeProperties(allow_discussion = False) - self.failIf(portal_discussion.isDiscussionAllowedFor(self.portal.doc1)) - self.failIf(self.portal.doc1.getTypeInfo().allowDiscussion()) + self.assertEquals(portal_discussion.isDiscussionAllowedFor(self.portal.doc1), False) + self.assertEquals(self.portal.doc1.getTypeInfo().allowDiscussion(), False) # Now we override allow_discussion again (True) for the Document # content object self.portal_discussion.overrideDiscussionFor(self.portal.doc1, True) - self.failUnless(portal_discussion.isDiscussionAllowedFor(self.portal.doc1)) + self.assertEquals(portal_discussion.isDiscussionAllowedFor(self.portal.doc1), True) + self.assertEquals(getattr(self.portal.doc1, 'allow_discussion', None), True) def test_disable_commenting_globally(self): @@ -277,20 +287,24 @@ class ConversationTest(PloneTestCase): self.typetool.constructContent('Folder', self.portal, 'f1') f1 = self.portal.f1 - # Create a document inside the folder with a conversation + # Create a document inside the folder self.typetool.constructContent('Document', f1, 'doc1') doc1 = self.portal.f1.doc1 - conversation = IConversation(self.portal.doc1) + doc1_conversation = IConversation(doc1) + + self.assertEquals(doc1_conversation.enabled(), False) # Allow commenting for the folder self.portal_discussion.overrideDiscussionFor(f1, True) # Check if the content objects allows discussion - #self.assertEquals(conversation.enabled(), True) + self.assertEquals(doc1_conversation.enabled(), True) # Turn commenting for the folder off + self.portal_discussion.overrideDiscussionFor(f1, False) # Check if content objects do not allow discussion anymore + self.assertEquals(doc1_conversation.enabled(), False) def test_is_discussion_allowed_on_content_object(self): # Allow discussion on a single content object