Back to index

plone3  3.1.7
DiscussionTool.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Basic portal discussion access tool.
00014 
00015 $Id: DiscussionTool.py 77113 2007-06-26 20:36:26Z yuppie $
00016 """
00017 
00018 import urllib
00019 
00020 from AccessControl import ClassSecurityInfo
00021 from Acquisition import Implicit
00022 from DateTime.DateTime import DateTime
00023 from Globals import DTMLFile
00024 from Globals import InitializeClass
00025 from OFS.SimpleItem import SimpleItem
00026 from zope.interface import implements
00027 
00028 from ActionProviderBase import ActionProviderBase
00029 from interfaces import IOldstyleDiscussable
00030 from interfaces import IOldstyleDiscussionTool
00031 from interfaces.Discussions import OldDiscussable as z2IOldstyleDiscussable
00032 from interfaces.portal_discussion \
00033         import oldstyle_portal_discussion as z2IOldstyleDiscussionTool
00034 from permissions import AccessContentsInformation
00035 from permissions import ManagePortal
00036 from permissions import ReplyToItem
00037 from permissions import View
00038 from utils import _dtmldir
00039 from utils import getToolByName
00040 from utils import UniqueObject
00041 
00042 
00043 class OldDiscussable(Implicit):
00044 
00045     """
00046         Adapter for PortalContent to implement "old-style" discussions.
00047     """
00048 
00049     implements(IOldstyleDiscussable)
00050     __implements__ = z2IOldstyleDiscussable
00051 
00052     security = ClassSecurityInfo()
00053 
00054     def __init__( self, content ):
00055         self.content = content
00056 
00057     security.declareProtected(ReplyToItem, 'createReply')
00058     def createReply(self, title, text, REQUEST, RESPONSE):
00059         """
00060             Create a reply in the proper place
00061         """
00062 
00063         location, id = self.getReplyLocationAndID(REQUEST)
00064         location.addDiscussionItem(id, title, title, 'structured-text',
00065                                    text, self.content)
00066 
00067         RESPONSE.redirect( self.absolute_url() + '/view' )
00068 
00069     def getReplyLocationAndID(self, REQUEST):
00070         # It is not yet clear to me what the correct location for this hook is
00071 
00072         # Find the folder designated for replies, creating if missing
00073         membershiptool = getToolByName(self.content, 'portal_membership')
00074         home = membershiptool.getHomeFolder()
00075         if not hasattr(home, 'Correspondence'):
00076             home.manage_addPortalFolder('Correspondence')
00077         location = home.Correspondence
00078         location.manage_permission(View, ['Anonymous'], 1)
00079         location.manage_permission(AccessContentsInformation, ['Anonymous'], 1)
00080 
00081         # Find an unused id in location
00082         id = int(DateTime().timeTime())
00083         while hasattr(location, `id`):
00084             id = id + 1
00085 
00086         return location, `id`
00087 
00088     security.declareProtected(View, 'getReplyResults')
00089     def getReplyResults(self):
00090         """
00091             Return the ZCatalog results that represent this object's replies.
00092 
00093             Often, the actual objects are not needed.  This is less expensive
00094             than fetching the objects.
00095         """
00096         catalog = getToolByName(self.content, 'portal_catalog')
00097         return catalog.searchResults(in_reply_to=
00098                                       urllib.unquote('/'+self.absolute_url(1)))
00099 
00100     security.declareProtected(View, 'getReplies')
00101     def getReplies(self):
00102         """
00103             Return a sequence of the DiscussionResponse objects which are
00104             associated with this Discussable
00105         """
00106         catalog = getToolByName(self.content, 'portal_catalog')
00107         results = self.getReplyResults()
00108         rids    = map(lambda x: x.data_record_id_, results)
00109         objects = map(catalog.getobject, rids)
00110         return objects
00111 
00112     def quotedContents(self):
00113         """
00114             Return this object's contents in a form suitable for inclusion
00115             as a quote in a response.
00116         """
00117 
00118         return ""
00119 
00120 
00121 class DiscussionTool(UniqueObject, SimpleItem, ActionProviderBase):
00122 
00123     implements(IOldstyleDiscussionTool)
00124     __implements__ = (z2IOldstyleDiscussionTool,
00125                       ActionProviderBase.__implements__)
00126 
00127     id = 'portal_discussion'
00128     meta_type = 'Oldstyle CMF Discussion Tool'
00129     # This tool is used to find the discussion for a given content object.
00130 
00131     security = ClassSecurityInfo()
00132 
00133     manage_options = ( { 'label' : 'Overview', 'action' : 'manage_overview' }
00134                      ,
00135                      ) + SimpleItem.manage_options
00136 
00137     #
00138     #   ZMI methods
00139     #
00140     security.declareProtected(ManagePortal, 'manage_overview')
00141     manage_overview = DTMLFile( 'explainDiscussionTool', _dtmldir )
00142 
00143     #
00144     #   'portal_discussion' interface methods
00145     #
00146     security.declarePublic('getDiscussionFor')
00147     def getDiscussionFor(self, content):
00148         '''Gets the PortalDiscussion object that applies to content.
00149         '''
00150         return OldDiscussable( content ).__of__( content )
00151 
00152     security.declarePublic('isDiscussionAllowedFor')
00153     def isDiscussionAllowedFor(self, content):
00154         '''
00155             Returns a boolean indicating whether a discussion is
00156             allowed for the specified content.
00157         '''
00158         if hasattr( content, 'allow_discussion' ):
00159             return content.allow_discussion
00160         typeInfo = content.getTypeInfo()
00161         if typeInfo:
00162             return typeInfo.allowDiscussion()
00163         return 0
00164 
00165     security.declarePrivate('listActions')
00166     def listActions(self, info=None, object=None):
00167         # Return actions for reply and show replies
00168         if object is not None or info is None:
00169             info = self._getOAI(object)
00170         content = info.object
00171         if content is None or not self.isDiscussionAllowedFor(content):
00172             return ()
00173 
00174         discussion = self.getDiscussionFor(content)
00175         if discussion.aq_base == content.aq_base:
00176             discussion_url = info.object_url
00177         else:
00178             discussion_url = discussion.absolute_url()
00179 
00180         actions = (
00181             {'name': 'Reply',
00182              'url': discussion_url + '/discussion_reply_form',
00183              'permissions': [ReplyToItem],
00184              'category': 'object'
00185              },
00186             )
00187 
00188         return actions
00189 
00190 InitializeClass(DiscussionTool)