vendor/CMF/1.5.5-beta/CMFTopic

view Topic.py @ 0:4341d8feb2f9

Vendor import of CMF 1.5.5-beta
author fguillaume
date Mon, 07 Nov 2005 22:03:41 +0000
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 """ Topic: Canned catalog queries
15 $Id: Topic.py 38001 2005-08-18 23:37:25Z jens $
16 """
18 from AccessControl import ClassSecurityInfo
19 from Acquisition import aq_parent, aq_inner, aq_base
20 from Globals import InitializeClass
22 from Products.CMFDefault.SkinnedFolder import SkinnedFolder
23 from Products.CMFCore.utils import _getViewFor
24 from Products.CMFCore.utils import getToolByName
26 from permissions import ListFolderContents
27 from permissions import View
28 from permissions import AddTopics
29 from permissions import ChangeTopics
32 # Factory type information -- makes Topic objects play nicely
33 # with the Types Tool (portal_types )
34 factory_type_information = (
35 { 'id' : 'Topic'
36 , 'icon' : 'topic_icon.gif'
37 , 'meta_type' : 'Portal Topic'
38 , 'description' : 'Topics are canned queries for organizing content '
39 'with up to date queries into the catalog.'
40 , 'product' : 'CMFTopic'
41 , 'factory' : 'addTopic'
42 , 'immediate_view' : 'topic_edit_form'
43 , 'allowed_content_types': ('Topic',)
44 , 'aliases' : {'(Default)': 'topic_view',
45 'view': 'topic_view'}
46 , 'actions' : ( { 'id' : 'view'
47 , 'name' : 'View'
48 , 'action': 'string:${object_url}/topic_view'
49 , 'permissions' : (View,)
50 }
51 , { 'id' : 'edit'
52 , 'name' : 'Edit'
53 , 'action': 'string:${object_url}/topic_edit_form'
54 , 'permissions' : (ChangeTopics,)
55 }
56 , { 'id' : 'criteria'
57 , 'name' : 'Criteria'
58 , 'action': 'string:${object_url}/topic_criteria_form'
59 , 'permissions' : (ChangeTopics,)
60 }
61 , { 'id' : 'folderContents'
62 , 'name' : 'Subtopics'
63 , 'action': 'string:${object_url}/folder_contents'
64 , 'permissions' : (ListFolderContents,)
65 }
66 , { 'id' : 'new'
67 , 'name' : 'New...'
68 , 'action': 'string:${object_url}/folder_factories'
69 , 'permissions' : (AddTopics,)
70 , 'visible' : 0
71 }
72 , { 'id' : 'rename_items'
73 , 'name' : 'Rename items'
74 , 'action': 'string:${object_url}/folder_rename_form'
75 , 'permissions' : (AddTopics,)
76 , 'visible' : 0
77 }
78 )
79 }
80 ,
81 )
83 def addTopic( self, id, title='', REQUEST=None ):
85 """ Create an empty topic.
86 """
87 topic = Topic( id )
88 topic.id = id
89 topic.title = title
90 self._setObject( id, topic )
92 if REQUEST is not None:
93 REQUEST['RESPONSE'].redirect( 'manage_main' )
96 class Topic( SkinnedFolder ):
98 """ Topics are 'canned queries'
100 o Each topic holds a set of zero or more Criteria objects specifying
101 the query.
102 """
104 meta_type='Portal Topic'
106 security = ClassSecurityInfo()
107 security.declareObjectProtected(View)
109 acquireCriteria = 1
110 _criteriaTypes = []
112 def __call__( self ):
113 """ Invoke the default action.
114 """
115 ti = self.getTypeInfo()
116 method_id = ti and ti.queryMethodID('(Default)', context=self)
117 if method_id:
118 method = getattr(self, method_id)
119 else:
120 method = _getViewFor(self)
122 if getattr(aq_base(method), 'isDocTemp', 0):
123 return method(self, self.REQUEST, self.REQUEST['RESPONSE'])
124 else:
125 return method()
127 index_html = None # This special value informs ZPublisher to use __call__
129 security.declareProtected(View, 'view')
130 def view( self ):
132 """ Return the default view even if index_html is overridden.
133 """
134 return self()
136 security.declareProtected(ChangeTopics, 'listCriteria')
137 def listCriteria( self ):
139 """ Return a list of our criteria objects.
140 """
141 return self.objectValues( self._criteria_metatype_ids() )
144 security.declareProtected(ChangeTopics, 'listCriteriaTypes')
145 def listCriteriaTypes( self ):
147 """ List the available criteria types.
148 """
149 out = []
151 for ct in self._criteriaTypes:
152 out.append( { 'name': ct.meta_type } )
154 return out
156 security.declareProtected(ChangeTopics, 'listAvailableFields')
157 def listAvailableFields( self ):
159 """ Return a list of available fields for new criteria.
160 """
161 portal_catalog = getToolByName( self, 'portal_catalog' )
162 currentfields = map( lambda x: x.Field(), self.listCriteria() )
163 availfields = filter(
164 lambda field, cf=currentfields: field not in cf,
165 portal_catalog.indexes()
166 )
167 return availfields
169 security.declareProtected(ChangeTopics, 'listSubtopics')
170 def listSubtopics( self ):
172 """ Return a list of our subtopics.
173 """
174 return self.objectValues( self.meta_type )
176 security.declareProtected(ChangeTopics, 'edit')
177 def edit( self, acquireCriteria, title=None, description=None ):
179 """ Set the flag which indicates whether to acquire criteria.
181 o If set, reuse creiteria from parent topics;
183 o Also update metadata about the Topic.
184 """
185 self.acquireCriteria = acquireCriteria
186 if title is not None:
187 self.title = title
188 self.description = description
190 self.reindexObject()
192 security.declareProtected(View, 'buildQuery')
193 def buildQuery( self ):
195 """ Construct a catalog query using our criterion objects.
196 """
197 result = {}
199 if self.acquireCriteria:
201 try:
202 # Tracker 290 asks to allow combinations, like this:
203 # parent = aq_parent( self )
204 parent = aq_parent( aq_inner( self ) )
205 result.update( parent.buildQuery() )
207 except: # oh well, can't find parent, or it isn't a Topic.
208 pass
210 for criterion in self.listCriteria():
212 for key, value in criterion.getCriteriaItems():
213 result[ key ] = value
215 return result
217 security.declareProtected(View, 'queryCatalog')
218 def queryCatalog( self, REQUEST=None, **kw ):
220 """ Invoke the catalog using our criteria.
222 o Built-in criteria update any criteria passed in 'kw'.
223 """
224 kw.update( self.buildQuery() )
225 portal_catalog = getToolByName( self, 'portal_catalog' )
226 return portal_catalog.searchResults(REQUEST, **kw)
228 security.declareProtected(View, 'synContentValues')
229 def synContentValues( self ):
231 """ Return a limited subset of the brains for our query.
233 o Return no more brain objects than the limit set by the
234 syndication tool.
235 """
236 syn_tool = getToolByName( self, 'portal_syndication' )
237 limit = syn_tool.getMaxItems( self )
238 brains = self.queryCatalog( sort_limit=limit )[ :limit ]
239 return [ brain.getObject() for brain in brains ]
241 ### Criteria adding/editing/deleting
242 security.declareProtected(ChangeTopics, 'addCriterion')
243 def addCriterion( self, field, criterion_type ):
245 """ Add a new search criterion.
246 """
247 crit = None
248 newid = 'crit__%s' % field
250 for ct in self._criteriaTypes:
252 if criterion_type == ct.meta_type:
253 crit = ct( newid, field )
255 if crit is None:
256 # No criteria type matched passed in value
257 raise NameError, 'Unknown Criterion Type: %s' % criterion_type
259 self._setObject( newid, crit )
261 security.declareProtected(ChangeTopics, 'deleteCriterion')
262 def deleteCriterion( self, criterion_id ):
264 """ Delete selected criterion.
265 """
266 if type( criterion_id ) is type( '' ):
267 self._delObject( criterion_id )
268 elif type( criterion_id ) in ( type( () ), type( [] ) ):
269 for cid in criterion_id:
270 self._delObject( cid )
272 security.declareProtected(View, 'getCriterion')
273 def getCriterion( self, criterion_id ):
275 """ Get the criterion object.
276 """
277 try:
278 return self._getOb( 'crit__%s' % criterion_id )
279 except AttributeError:
280 return self._getOb( criterion_id )
282 security.declareProtected(AddTopics, 'addSubtopic')
283 def addSubtopic( self, id ):
285 """ Add a new subtopic.
286 """
287 ti = self.getTypeInfo()
288 ti.constructInstance(self, id)
289 return self._getOb( id )
291 #
292 # Helper methods
293 #
294 security.declarePrivate( '_criteria_metatype_ids' )
295 def _criteria_metatype_ids( self ):
297 result = []
299 for mt in self._criteriaTypes:
300 result.append( mt.meta_type )
302 return tuple( result )
304 #
305 # Cataloging helper to make finding this item easier
306 #
307 security.declareProtected(View, 'SearchableText')
308 def SearchableText(self):
309 """
310 SeachableText is used for full text seraches of a portal. It
311 should return a concatenation of all useful text.
312 """
313 return "%s %s" % (self.title, self.description)
315 InitializeClass( Topic )