vendor/CMF/1.6.3/CMFCore

view ContentTypeRegistry.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 Site content type registry
15 $Id$
16 """
18 import re, os, urllib
20 from AccessControl import ClassSecurityInfo
21 from Globals import DTMLFile
22 from Globals import InitializeClass
23 from Globals import PersistentMapping
24 from OFS.SimpleItem import SimpleItem
25 from ZPublisher.mapply import mapply
27 from interfaces.ContentTypeRegistry \
28 import ContentTypeRegistry as z2IContentTypeRegistry
29 from interfaces.ContentTypeRegistry \
30 import ContentTypeRegistryPredicate as z2IContentTypeRegistryPredicate
31 from permissions import ManagePortal
32 from utils import _dtmldir
33 from utils import getToolByName
35 from zope.interface import implements
36 from interfaces import IContentTypeRegistry
37 from interfaces import IContentTypeRegistryPredicate
39 class MajorMinorPredicate( SimpleItem ):
40 """
41 Predicate matching on 'major/minor' content types.
42 Empty major or minor implies wildcard (all match).
43 """
45 __implements__ = z2IContentTypeRegistryPredicate
46 implements(IContentTypeRegistryPredicate)
48 major = minor = None
49 PREDICATE_TYPE = 'major_minor'
51 security = ClassSecurityInfo()
53 def __init__( self, id ):
54 self.id = id
56 security.declareProtected( ManagePortal, 'getMajorType' )
57 def getMajorType(self):
58 """ Get major content types.
59 """
60 if self.major is None:
61 return 'None'
62 return ' '.join(self.major)
64 security.declareProtected( ManagePortal, 'getMinorType' )
65 def getMinorType(self):
66 """ Get minor content types.
67 """
68 if self.minor is None:
69 return 'None'
70 return ' '.join(self.minor)
72 security.declareProtected( ManagePortal, 'edit' )
73 def edit( self, major, minor, COMMA_SPLIT=re.compile( r'[, ]' ) ):
75 if major == 'None':
76 major = None
77 if type( major ) is type( '' ):
78 major = filter( None, COMMA_SPLIT.split( major ) )
80 if minor == 'None':
81 minor = None
82 if type( minor ) is type( '' ):
83 minor = filter( None, COMMA_SPLIT.split( minor ) )
85 self.major = major
86 self.minor = minor
88 #
89 # ContentTypeRegistryPredicate interface
90 #
91 security.declareObjectPublic()
92 def __call__( self, name, typ, body ):
93 """
94 Return true if the rule matches, else false.
95 """
96 if self.major is None:
97 return 0
99 if self.minor is None:
100 return 0
102 typ = typ or '/'
103 if not '/' in typ:
104 typ = typ + '/'
105 major, minor = typ.split('/', 1)
107 if self.major and not major in self.major:
108 return 0
110 if self.minor and not minor in self.minor:
111 return 0
113 return 1
115 security.declareProtected( ManagePortal, 'getTypeLabel' )
116 def getTypeLabel( self ):
117 """
118 Return a human-readable label for the predicate type.
119 """
120 return self.PREDICATE_TYPE
122 security.declareProtected( ManagePortal, 'predicateWidget' )
123 predicateWidget = DTMLFile( 'majorMinorWidget', _dtmldir )
125 InitializeClass( MajorMinorPredicate )
127 class ExtensionPredicate( SimpleItem ):
128 """
129 Predicate matching on filename extensions.
130 """
132 __implements__ = z2IContentTypeRegistryPredicate
133 implements(IContentTypeRegistryPredicate)
135 extensions = None
136 PREDICATE_TYPE = 'extension'
138 security = ClassSecurityInfo()
140 def __init__( self, id ):
141 self.id = id
143 security.declareProtected( ManagePortal, 'getExtensions' )
144 def getExtensions(self):
145 """ Get filename extensions.
146 """
147 if self.extensions is None:
148 return 'None'
149 return ' '.join(self.extensions)
151 security.declareProtected( ManagePortal, 'edit' )
152 def edit( self, extensions, COMMA_SPLIT=re.compile( r'[, ]' ) ):
154 if extensions == 'None':
155 extensions = None
156 if type( extensions ) is type( '' ):
157 extensions = filter( None, COMMA_SPLIT.split( extensions ) )
159 self.extensions = extensions
161 #
162 # ContentTypeRegistryPredicate interface
163 #
164 security.declareObjectPublic()
165 def __call__( self, name, typ, body ):
166 """
167 Return true if the rule matches, else false.
168 """
169 if self.extensions is None:
170 return 0
172 base, ext = os.path.splitext( name )
173 if ext and ext[ 0 ] == '.':
174 ext = ext[ 1: ]
176 return ext in self.extensions
178 security.declareProtected( ManagePortal, 'getTypeLabel' )
179 def getTypeLabel( self ):
180 """
181 Return a human-readable label for the predicate type.
182 """
183 return self.PREDICATE_TYPE
185 security.declareProtected( ManagePortal, 'predicateWidget' )
186 predicateWidget = DTMLFile( 'extensionWidget', _dtmldir )
188 InitializeClass( ExtensionPredicate )
190 class MimeTypeRegexPredicate( SimpleItem ):
191 """
192 Predicate matching only on 'typ', using regex matching for
193 string patterns (other objects conforming to 'match' can
194 also be passed).
195 """
197 __implements__ = z2IContentTypeRegistryPredicate
198 implements(IContentTypeRegistryPredicate)
200 pattern = None
201 PREDICATE_TYPE = 'mimetype_regex'
203 security = ClassSecurityInfo()
205 def __init__( self, id ):
206 self.id = id
208 security.declareProtected( ManagePortal, 'getPatternStr' )
209 def getPatternStr( self ):
210 if self.pattern is None:
211 return 'None'
212 return self.pattern.pattern
214 security.declareProtected( ManagePortal, 'edit' )
215 def edit( self, pattern ):
216 if pattern == 'None':
217 pattern = None
218 if type( pattern ) is type( '' ):
219 pattern = re.compile( pattern )
220 self.pattern = pattern
222 #
223 # ContentTypeRegistryPredicate interface
224 #
225 security.declareObjectPublic()
226 def __call__( self, name, typ, body ):
227 """
228 Return true if the rule matches, else false.
229 """
230 if self.pattern is None:
231 return 0
233 return self.pattern.match( typ )
235 security.declareProtected( ManagePortal, 'getTypeLabel' )
236 def getTypeLabel( self ):
237 """
238 Return a human-readable label for the predicate type.
239 """
240 return self.PREDICATE_TYPE
242 security.declareProtected( ManagePortal, 'predicateWidget' )
243 predicateWidget = DTMLFile( 'patternWidget', _dtmldir )
245 InitializeClass( MimeTypeRegexPredicate )
247 class NameRegexPredicate( SimpleItem ):
248 """
249 Predicate matching only on 'name', using regex matching
250 for string patterns (other objects conforming to 'match'
251 and 'pattern' can also be passed).
252 """
254 __implements__ = z2IContentTypeRegistryPredicate
255 implements(IContentTypeRegistryPredicate)
257 pattern = None
258 PREDICATE_TYPE = 'name_regex'
260 security = ClassSecurityInfo()
262 def __init__( self, id ):
263 self.id = id
265 security.declareProtected( ManagePortal, 'getPatternStr' )
266 def getPatternStr( self ):
267 """
268 Return a string representation of our pattern.
269 """
270 if self.pattern is None:
271 return 'None'
272 return self.pattern.pattern
274 security.declareProtected( ManagePortal, 'edit' )
275 def edit( self, pattern ):
276 if pattern == 'None':
277 pattern = None
278 if type( pattern ) is type( '' ):
279 pattern = re.compile( pattern )
280 self.pattern = pattern
282 #
283 # ContentTypeRegistryPredicate interface
284 #
285 security.declareObjectPublic()
286 def __call__( self, name, typ, body ):
287 """
288 Return true if the rule matches, else false.
289 """
290 if self.pattern is None:
291 return 0
293 return self.pattern.match( name )
295 security.declareProtected( ManagePortal, 'getTypeLabel' )
296 def getTypeLabel( self ):
297 """
298 Return a human-readable label for the predicate type.
299 """
300 return self.PREDICATE_TYPE
302 security.declareProtected( ManagePortal, 'predicateWidget' )
303 predicateWidget = DTMLFile( 'patternWidget', _dtmldir )
305 InitializeClass( NameRegexPredicate )
308 _predicate_types = []
310 def registerPredicateType( typeID, klass ):
311 """
312 Add a new predicate type.
313 """
314 _predicate_types.append( ( typeID, klass ) )
316 for klass in ( MajorMinorPredicate
317 , ExtensionPredicate
318 , MimeTypeRegexPredicate
319 , NameRegexPredicate
320 ):
321 registerPredicateType( klass.PREDICATE_TYPE, klass )
324 class ContentTypeRegistry( SimpleItem ):
325 """
326 Registry for rules which map PUT args to a CMF Type Object.
327 """
329 __implements__ = z2IContentTypeRegistry
330 implements(IContentTypeRegistry)
332 meta_type = 'Content Type Registry'
333 id = 'content_type_registry'
335 manage_options = ( { 'label' : 'Predicates'
336 , 'action' : 'manage_predicates'
337 }
338 , { 'label' : 'Test'
339 , 'action' : 'manage_testRegistry'
340 }
341 ) + SimpleItem.manage_options
343 security = ClassSecurityInfo()
345 def __init__( self ):
346 self.predicate_ids = ()
347 self.predicates = PersistentMapping()
349 #
350 # ZMI
351 #
352 security.declarePublic( 'listPredicateTypes' )
353 def listPredicateTypes( self ):
354 """
355 """
356 return map( lambda x: x[0], _predicate_types )
358 security.declareProtected( ManagePortal, 'manage_predicates' )
359 manage_predicates = DTMLFile( 'registryPredList', _dtmldir )
361 security.declareProtected( ManagePortal, 'doAddPredicate' )
362 def doAddPredicate( self, predicate_id, predicate_type, REQUEST ):
363 """
364 """
365 self.addPredicate( predicate_id, predicate_type )
366 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
367 + '/manage_predicates'
368 + '?manage_tabs_message=Predicate+added.'
369 )
371 security.declareProtected( ManagePortal, 'doUpdatePredicate' )
372 def doUpdatePredicate( self
373 , predicate_id
374 , predicate
375 , typeObjectName
376 , REQUEST
377 ):
378 """
379 """
380 self.updatePredicate( predicate_id, predicate, typeObjectName )
381 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
382 + '/manage_predicates'
383 + '?manage_tabs_message=Predicate+updated.'
384 )
386 security.declareProtected( ManagePortal, 'doMovePredicateUp' )
387 def doMovePredicateUp( self, predicate_id, REQUEST ):
388 """
389 """
390 predicate_ids = list( self.predicate_ids )
391 ndx = predicate_ids.index( predicate_id )
392 if ndx == 0:
393 msg = "Predicate+already+first."
394 else:
395 self.reorderPredicate( predicate_id, ndx - 1 )
396 msg = "Predicate+moved."
397 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
398 + '/manage_predicates'
399 + '?manage_tabs_message=%s' % msg
400 )
402 security.declareProtected( ManagePortal, 'doMovePredicateDown' )
403 def doMovePredicateDown( self, predicate_id, REQUEST ):
404 """
405 """
406 predicate_ids = list( self.predicate_ids )
407 ndx = predicate_ids.index( predicate_id )
408 if ndx == len( predicate_ids ) - 1:
409 msg = "Predicate+already+last."
410 else:
411 self.reorderPredicate( predicate_id, ndx + 1 )
412 msg = "Predicate+moved."
413 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
414 + '/manage_predicates'
415 + '?manage_tabs_message=%s' % msg
416 )
418 security.declareProtected( ManagePortal, 'doRemovePredicate' )
419 def doRemovePredicate( self, predicate_id, REQUEST ):
420 """
421 """
422 self.removePredicate( predicate_id )
423 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
424 + '/manage_predicates'
425 + '?manage_tabs_message=Predicate+removed.'
426 )
428 security.declareProtected( ManagePortal, 'manage_testRegistry' )
429 manage_testRegistry = DTMLFile( 'registryTest', _dtmldir )
431 security.declareProtected( ManagePortal, 'doTestRegistry' )
432 def doTestRegistry( self, name, content_type, body, REQUEST ):
433 """
434 """
435 typeName = self.findTypeName( name, content_type, body )
436 if typeName is None:
437 typeName = '<unknown>'
438 else:
439 types_tool = getToolByName(self, 'portal_types')
440 typeName = types_tool.getTypeInfo(typeName).Title()
441 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
442 + '/manage_testRegistry'
443 + '?testResults=Type:+%s'
444 % urllib.quote( typeName )
445 )
447 #
448 # Predicate manipulation
449 #
450 security.declarePublic( 'getPredicate' )
451 def getPredicate( self, predicate_id ):
452 """
453 Find the predicate whose id is 'id'; return the predicate
454 object, if found, or else None.
455 """
456 return self.predicates.get( predicate_id, ( None, None ) )[0]
458 security.declarePublic( 'listPredicates' )
459 def listPredicates( self ):
460 """
461 Return a sequence of tuples,
462 '( id, ( predicate, typeObjectName ) )'
463 for all predicates in the registry
464 """
465 result = []
466 for predicate_id in self.predicate_ids:
467 result.append( ( predicate_id, self.predicates[ predicate_id ] ) )
468 return tuple( result )
470 security.declarePublic( 'getTypeObjectName' )
471 def getTypeObjectName( self, predicate_id ):
472 """
473 Find the predicate whose id is 'id'; return the name of
474 the type object, if found, or else None.
475 """
476 return self.predicates.get( predicate_id, ( None, None ) )[1]
478 security.declareProtected( ManagePortal, 'addPredicate' )
479 def addPredicate( self, predicate_id, predicate_type ):
480 """
481 Add a predicate to this element of type 'typ' to the registry.
482 """
483 if predicate_id in self.predicate_ids:
484 raise ValueError, "Existing predicate: %s" % predicate_id
486 klass = None
487 for key, value in _predicate_types:
488 if key == predicate_type:
489 klass = value
491 if klass is None:
492 raise ValueError, "Unknown predicate type: %s" % predicate_type
494 self.predicates[ predicate_id ] = ( klass( predicate_id ), None )
495 self.predicate_ids = self.predicate_ids + ( predicate_id, )
497 security.declareProtected( ManagePortal, 'updatePredicate' )
498 def updatePredicate( self, predicate_id, predicate, typeObjectName ):
499 """
500 Update a predicate in this element.
501 """
502 if not predicate_id in self.predicate_ids:
503 raise ValueError, "Unknown predicate: %s" % predicate_id
505 predObj = self.predicates[ predicate_id ][0]
506 mapply( predObj.edit, (), predicate.__dict__ )
507 self.assignTypeName( predicate_id, typeObjectName )
509 security.declareProtected( ManagePortal, 'removePredicate' )
510 def removePredicate( self, predicate_id ):
511 """
512 Remove a predicate from the registry.
513 """
514 del self.predicates[ predicate_id ]
515 idlist = list( self.predicate_ids )
516 ndx = idlist.index( predicate_id )
517 idlist = idlist[ :ndx ] + idlist[ ndx+1: ]
518 self.predicate_ids = tuple( idlist )
520 security.declareProtected( ManagePortal, 'reorderPredicate' )
521 def reorderPredicate( self, predicate_id, newIndex ):
522 """
523 Move a given predicate to a new location in the list.
524 """
525 idlist = list( self.predicate_ids )
526 ndx = idlist.index( predicate_id )
527 pred = idlist[ ndx ]
528 idlist = idlist[ :ndx ] + idlist[ ndx+1: ]
529 idlist.insert( newIndex, pred )
530 self.predicate_ids = tuple( idlist )
532 security.declareProtected( ManagePortal, 'assignTypeName' )
533 def assignTypeName( self, predicate_id, typeObjectName ):
534 """
535 Bind the given predicate to a particular type object.
536 """
537 pred, oldTypeObjName = self.predicates[ predicate_id ]
538 self.predicates[ predicate_id ] = ( pred, typeObjectName )
540 #
541 # ContentTypeRegistry interface
542 #
543 def findTypeName( self, name, typ, body ):
544 """
545 Perform a lookup over a collection of rules, returning the
546 the name of the Type object corresponding to name/typ/body.
547 Return None if no match found.
548 """
549 for predicate_id in self.predicate_ids:
550 pred, typeObjectName = self.predicates[ predicate_id ]
551 if pred( name, typ, body ):
552 return typeObjectName
554 return None
556 InitializeClass( ContentTypeRegistry )
558 def manage_addRegistry( self, REQUEST=None ):
559 """
560 Add a CTR to self.
561 """
562 CTRID = ContentTypeRegistry.id
563 reg = ContentTypeRegistry()
564 self._setObject( CTRID, reg )
565 reg = self._getOb( CTRID )
567 if REQUEST is not None:
568 REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
569 + '/manage_main'
570 + '?manage_tabs_message=Registry+added.'
571 )