From 0e587a7d8536125acdd3bd385e880b60d6aec28e Mon Sep 17 00:00:00 2001 From: Timo Stollenwerk Date: Sat, 30 Jun 2012 10:59:49 +0200 Subject: [PATCH] Support for Dexterity added. --- CHANGES.txt | 4 +- plone/app/discussion/browser/conversation.py | 47 ++++++++++++++ .../app/discussion/tests/test_conversation.py | 62 +++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0dc41d5..9e18971 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,7 +4,9 @@ Changelog 2.1.8 (unreleased) ------------------ -- Nothing changed yet. +- Support for Dexterity added. The conversation enabled method now detects and + supports Dexterity-based content types. + [timo] 2.1.7 (2012-06-29) diff --git a/plone/app/discussion/browser/conversation.py b/plone/app/discussion/browser/conversation.py index e605354..d618e05 100644 --- a/plone/app/discussion/browser/conversation.py +++ b/plone/app/discussion/browser/conversation.py @@ -14,10 +14,22 @@ from Products.CMFPlone.interfaces import INonStructuralFolder from plone.app.discussion.interfaces import IDiscussionSettings +try: + from plone.dexterity.interfaces import IDexterityContent + DEXTERITY_INSTALLED = True +except: + DEXTERITY_INSTALLED = False + class ConversationView(object): def enabled(self): + if DEXTERITY_INSTALLED and IDexterityContent.providedBy(self.context): + return self._enabled_for_dexterity_types() + else: + return self._enabled_for_archetypes() + + def _enabled_for_archetypes(self): """ Returns True if discussion is enabled for this conversation. This method checks five different settings in order to figure out if @@ -94,3 +106,38 @@ class ConversationView(object): return False return True + + def _enabled_for_dexterity_types(self): + """ Returns True if discussion is enabled for this conversation. + + This method checks five different settings in order to figure out if + discussion is enable on a specific content object: + + 1) Check if discussion is enabled globally in the plone.app.discussion + registry/control panel. + + 2) Check if the allow_discussion boolean flag on the content object is + set. If it is set to True or False, return the value. If it set to + None, try further. + + 3) Check if discussion is allowed for the content type. + """ + context = aq_inner(self.context) + + # Fetch discussion registry + registry = queryUtility(IRegistry) + settings = registry.forInterface(IDiscussionSettings, check=False) + + # Check if discussion is allowed globally + if not settings.globally_enabled: + return False + + # Check if discussion is allowed on the content object + if hasattr(context, "allow_discussion"): + if context.allow_discussion is not None: + return context.allow_discussion + + # Check if discussion is allowed on the content type + portal_types = getToolByName(self, 'portal_types') + document_fti = getattr(portal_types, context.portal_type) + return document_fti.getProperty('allow_discussion') diff --git a/plone/app/discussion/tests/test_conversation.py b/plone/app/discussion/tests/test_conversation.py index a90b725..712800f 100644 --- a/plone/app/discussion/tests/test_conversation.py +++ b/plone/app/discussion/tests/test_conversation.py @@ -715,6 +715,68 @@ class ConversationTest(unittest.TestCase): IAnnotations(self.portal.doc1)) +class ConversationEnabledForDexterityTypesTest(unittest.TestCase): + + layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + setRoles(self.portal, TEST_USER_ID, ['Manager']) + interface.alsoProvides( + self.portal.REQUEST, + interfaces.IDiscussionLayer) + + typetool = self.portal.portal_types + typetool.constructContent('Document', self.portal, 'doc1') + + from plone.dexterity.interfaces import IDexterityContent + interface.alsoProvides( + self.portal.doc1, + IDexterityContent) + + def _makeOne(self, *args, **kw): + return self.portal.doc1.restrictedTraverse('@@conversation_view') + + def _globally_enable_discussion(self, value): + registry = queryUtility(IRegistry) + settings = registry.forInterface(IDiscussionSettings) + settings.globally_enabled = value + + def _enable_discussion_on_portal_type(self, portal_type, allow_discussion): + portal_types = getToolByName(self.portal, 'portal_types') + document_fti = getattr(portal_types, portal_type) + document_fti.manage_changeProperties(allow_discussion=allow_discussion) + + def test_conversation_is_not_enabled_by_default(self): + conversation = self._makeOne(self.portal.doc1) + self.assertFalse(conversation.enabled()) + + def test_conversation_is_not_enabled_by_default_on_portal_type(self): + self._globally_enable_discussion(True) + conversation = self._makeOne(self.portal.doc1) + self.assertFalse(conversation.enabled()) + + def test_conversation_needs_to_be_enabled_globally_and_for_type(self): + self._globally_enable_discussion(True) + self._enable_discussion_on_portal_type('Document', True) + conversation = self._makeOne(self.portal.doc1) + self.assertTrue(conversation.enabled()) + + def test_disable_discussion(self): + self._globally_enable_discussion(True) + self._enable_discussion_on_portal_type('Document', True) + self.portal.doc1.allow_discussion = False + conversation = self._makeOne(self.portal.doc1) + self.assertFalse(conversation.enabled()) + + def test_enable_discussion(self): + self._globally_enable_discussion(True) + self._enable_discussion_on_portal_type('Document', True) + self.portal.doc1.allow_discussion = True + conversation = self._makeOne(self.portal.doc1) + self.assertTrue(conversation.enabled()) + + class RepliesTest(unittest.TestCase): # test the IReplies adapter on a conversation