vendor/CMF/1.6.3/CMFCore

view DiscussionTool.py @ 2:4c712d7bd1d7

Added tag 1.6.3 for changeset 1babb9d61518
author Georges Racinet on purity.racinet.fr <georges@racinet.fr>
date Fri, 09 Sep 2011 12:44:00 +0200
parents
children
line source
1 ##############################################################################
2 #
3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
4 #
5 # This software is subject to the provisions of the Zope Public License,
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
10 # FOR A PARTICULAR PURPOSE.
11 #
12 ##############################################################################
13 """ Basic portal discussion access tool.
15 $Id$
16 """
18 from OFS.SimpleItem import SimpleItem
19 from Globals import InitializeClass, DTMLFile
20 from Acquisition import Implicit
21 from AccessControl import ClassSecurityInfo
23 from ActionProviderBase import ActionProviderBase
24 from permissions import AccessContentsInformation
25 from permissions import ManagePortal
26 from permissions import ReplyToItem
27 from permissions import View
28 from interfaces.Discussions import OldDiscussable as IOldDiscussable
29 from interfaces.portal_discussion \
30 import oldstyle_portal_discussion as IOldstyleDiscussionTool
31 from utils import _dtmldir
32 from utils import getToolByName
33 from utils import UniqueObject
36 class OldDiscussable(Implicit):
37 """
38 Adapter for PortalContent to implement "old-style" discussions.
39 """
41 __implements__ = IOldDiscussable
43 _isDiscussable = 1
45 security = ClassSecurityInfo()
48 def __init__( self, content ):
49 self.content = content
51 security.declareProtected(ReplyToItem, 'createReply')
52 def createReply(self, title, text, REQUEST, RESPONSE):
53 """
54 Create a reply in the proper place
55 """
57 location, id = self.getReplyLocationAndID(REQUEST)
58 location.addDiscussionItem(id, title, title, 'structured-text',
59 text, self.content)
61 RESPONSE.redirect( self.absolute_url() + '/view' )
63 def getReplyLocationAndID(self, REQUEST):
64 # It is not yet clear to me what the correct location for this hook is
66 # Find the folder designated for replies, creating if missing
67 membershiptool = getToolByName(self.content, 'portal_membership')
68 home = membershiptool.getHomeFolder()
69 if not hasattr(home, 'Correspondence'):
70 home.manage_addPortalFolder('Correspondence')
71 location = home.Correspondence
72 location.manage_permission(View, ['Anonymous'], 1)
73 location.manage_permission(AccessContentsInformation, ['Anonymous'], 1)
75 # Find an unused id in location
76 id = int(DateTime().timeTime())
77 while hasattr(location, `id`):
78 id = id + 1
80 return location, `id`
82 security.declareProtected(View, 'getReplyResults')
83 def getReplyResults(self):
84 """
85 Return the ZCatalog results that represent this object's replies.
87 Often, the actual objects are not needed. This is less expensive
88 than fetching the objects.
89 """
90 catalog = getToolByName(self.content, 'portal_catalog')
91 return catalog.searchResults(in_reply_to=
92 urllib.unquote('/'+self.absolute_url(1)))
94 security.declareProtected(View, 'getReplies')
95 def getReplies(self):
96 """
97 Return a sequence of the DiscussionResponse objects which are
98 associated with this Discussable
99 """
100 catalog = getToolByName(self.content, 'portal_catalog')
101 results = self.getReplyResults()
102 rids = map(lambda x: x.data_record_id_, results)
103 objects = map(catalog.getobject, rids)
104 return objects
106 def quotedContents(self):
107 """
108 Return this object's contents in a form suitable for inclusion
109 as a quote in a response.
110 """
112 return ""
115 class DiscussionTool (UniqueObject, SimpleItem, ActionProviderBase):
117 __implements__ = (IOldstyleDiscussionTool,
118 ActionProviderBase.__implements__)
120 id = 'portal_discussion'
121 meta_type = 'Oldstyle CMF Discussion Tool'
122 # This tool is used to find the discussion for a given content object.
124 security = ClassSecurityInfo()
126 manage_options = ( { 'label' : 'Overview', 'action' : 'manage_overview' }
127 ,
128 ) + SimpleItem.manage_options
130 #
131 # ZMI methods
132 #
133 security.declareProtected(ManagePortal, 'manage_overview')
134 manage_overview = DTMLFile( 'explainDiscussionTool', _dtmldir )
136 #
137 # 'portal_discussion' interface methods
138 #
139 security.declarePublic('getDiscussionFor')
140 def getDiscussionFor(self, content):
141 '''Gets the PortalDiscussion object that applies to content.
142 '''
143 return OldDiscussable( content ).__of__( content )
145 security.declarePublic('isDiscussionAllowedFor')
146 def isDiscussionAllowedFor(self, content):
147 '''
148 Returns a boolean indicating whether a discussion is
149 allowed for the specified content.
150 '''
151 if hasattr( content, 'allow_discussion' ):
152 return content.allow_discussion
153 typeInfo = getToolByName(self, 'portal_types').getTypeInfo( content )
154 if typeInfo:
155 return typeInfo.allowDiscussion()
156 return 0
158 security.declarePrivate('listActions')
159 def listActions(self, info=None, object=None):
160 # Return actions for reply and show replies
161 if object is not None or info is None:
162 info = self._getOAI(object)
163 content = info.object
164 if content is None or not self.isDiscussionAllowedFor(content):
165 return ()
167 discussion = self.getDiscussionFor(content)
168 if discussion.aq_base == content.aq_base:
169 discussion_url = info.object_url
170 else:
171 discussion_url = discussion.absolute_url()
173 actions = (
174 {'name': 'Reply',
175 'url': discussion_url + '/discussion_reply_form',
176 'permissions': [ReplyToItem],
177 'category': 'object'
178 },
179 )
181 return actions
183 InitializeClass(DiscussionTool)