Back to index

plone3  3.1.7
ExtensibleMetadata.py
Go to the documentation of this file.
00001 import string
00002 from logging import INFO, DEBUG
00003 from zope.component import queryUtility
00004 
00005 from Products.Archetypes import PloneMessageFactory as _
00006 from Products.Archetypes.Field import *
00007 from Products.Archetypes.Widget import *
00008 from Products.Archetypes.Schema import Schema
00009 from Products.Archetypes.Schema import MetadataSchema
00010 from Products.Archetypes.interfaces.metadata import IExtensibleMetadata
00011 from Products.Archetypes.utils import DisplayList, shasattr
00012 from Products.Archetypes.debug import log
00013 from Products.Archetypes import config
00014 import Persistence
00015 from Acquisition import aq_base
00016 from AccessControl import ClassSecurityInfo
00017 from AccessControl import Unauthorized
00018 from DateTime.DateTime import DateTime
00019 from Globals import InitializeClass, DTMLFile
00020 from Products.CMFCore import permissions
00021 from Products.CMFCore.utils  import getToolByName
00022 from Products.CMFDefault.utils import _dtmldir
00023 from ComputedAttribute import ComputedAttribute
00024 
00025 _marker=[]
00026 
00027 # http://www.zope.org/Collectors/CMF/325
00028 # http://www.zope.org/Collectors/CMF/476
00029 _zone = DateTime().timezone()
00030 
00031 FLOOR_DATE = DateTime(1000, 1) # always effective
00032 CEILING_DATE = DateTime(2500, 0) # never expires
00033 
00034 # We import this conditionally, in order not to introduce a hard dependency
00035 try:
00036     from plone.i18n.locales.interfaces import IMetadataLanguageAvailability
00037     HAS_PLONE_I18N = True
00038 except ImportError:
00039     HAS_PLONE_I18N = False
00040 
00041 ## MIXIN
00042 class ExtensibleMetadata(Persistence.Persistent):
00043     """a replacement for CMFDefault.DublinCore.DefaultDublinCoreImpl
00044     """
00045     # XXX This is not completely true. We need to review this later
00046     # and make sure it is true.
00047     # Just so you know, the problem here is that Title
00048     # is on BaseObject.schema, so it does implement IExtensibleMetadata
00049     # as long as both are used together.
00050     __implements__ = IExtensibleMetadata
00051 
00052     security = ClassSecurityInfo()
00053 
00054     schema = type = MetadataSchema(
00055         (
00056         BooleanField(
00057             'allowDiscussion',
00058             accessor="isDiscussable",
00059             mutator="allowDiscussion",
00060             edit_accessor="editIsDiscussable",
00061             default=None,
00062             enforceVocabulary=1,
00063             widget=BooleanWidget(
00064                 label=_(u'label_allow_comments',
00065                         default=u'Allow comments'),
00066                 description=_(u'help_allow_comments',
00067                               default=u'If selected, users can add comments '
00068                                        'to this item.')
00069                 ),
00070         ),
00071         LinesField(
00072             'subject',
00073             multiValued=1,
00074             accessor="Subject",
00075             searchable=True,
00076             widget=KeywordWidget(
00077                 label=_(u'label_categories', default=u'Categories'),
00078                 description=_(u'help_categories',
00079                               default=u'Also known as keywords, tags or labels, '
00080                                        'these help you categorize your content.'),
00081                 ),
00082         ),
00083         TextField(
00084             'description',
00085             default='',
00086             searchable=1,
00087             accessor="Description",
00088             default_content_type = 'text/plain',
00089             allowable_content_types = ('text/plain',),
00090             widget=TextAreaWidget(
00091                 label=_(u'label_description', default=u'Description'),
00092                 description=_(u'help_description',
00093                               default=u'A short summary of the content.'),
00094                 ),
00095         ),
00096         # Location, also known as Coverage in the DC metadata standard, but we
00097         # keep the term Location here for historical reasons.
00098         StringField(
00099             'location',
00100             searchable=True,
00101             widget = StringWidget(
00102                 label = _(u'label_location', default=u'Location'),
00103                 description=_(u'help_location_dc',
00104                               default=u'The geographical location associated with the item, if applicable.'),
00105                 ),
00106         ),
00107         LinesField(
00108             'contributors',
00109             accessor="Contributors",
00110             widget=LinesWidget(
00111                 label=_(u'label_contributors', u'Contributors'),
00112                 description=_(u'help_contributors',
00113                               default=u"The names of people that have contributed "
00114                                        "to this item. Each contributor should "
00115                                        "be on a separate line."),
00116                 ),
00117         ),
00118         LinesField(
00119             'creators',
00120             accessor="Creators",
00121             widget=LinesWidget(
00122                 label=_(u'label_creators', u'Creators'),
00123                 description=_(u'help_creators',
00124                               default=u"Persons responsible for creating the content of "
00125                                        "this item. Please enter a list of user names, one "
00126                                        "per line. The principal creator should come first."),
00127                 rows = 3
00128                 ),
00129         ),
00130         DateTimeField(
00131             'effectiveDate',
00132             mutator='setEffectiveDate',
00133             languageIndependent = True,
00134             widget=CalendarWidget(
00135                 label=_(u'label_effective_date', u'Publishing Date'),
00136                 description=_(u'help_effective_date',
00137                               default=u"If this date is in the future, the content will "
00138                                        "not show up in listings and searches until this date."),
00139                 ),
00140         ),
00141         DateTimeField(
00142             'expirationDate',
00143             mutator='setExpirationDate',
00144             languageIndependent = True,
00145             widget=CalendarWidget(
00146                 label=_(u'label_expiration_date', u'Expiration Date'),
00147                 description=_(u'help_expiration_date',
00148                               default=u"When this date is reached, the content will no"
00149                                        "longer be visible in listings and searches."),
00150                 ),
00151         ),
00152         StringField(
00153             'language',
00154             accessor="Language",
00155             default = config.LANGUAGE_DEFAULT,
00156             default_method = 'defaultLanguage',
00157             vocabulary='languages',
00158             widget=LanguageWidget(
00159                 label=_(u'label_language', default=u'Language'),
00160                 ),
00161         ),
00162         TextField(
00163             'rights',
00164             accessor="Rights",
00165             default_method='defaultRights',
00166             widget=TextAreaWidget(
00167                 label=_(u'label_copyrights', default=u'Rights'),
00168                 description=_(u'help_copyrights',
00169                               default=u'Copyright statement or other rights information on this item.'),
00170                 )),
00171         )) + Schema((
00172         # XXX change this to MetadataSchema in AT 1.4
00173         # Currently we want to stay backward compatible without migration
00174         # between beta versions so creation and modification date are using the
00175         # standard schema which leads to AttributeStorage
00176         DateTimeField(
00177             'creation_date',
00178             accessor='created',
00179             mutator='setCreationDate',
00180             default_method=DateTime,
00181             languageIndependent=True,
00182             isMetadata=True,
00183             schemata='metadata',
00184             generateMode='mVc',
00185             widget=CalendarWidget(
00186                 label=_(u'label_creation_date', default=u'Creation Date'),
00187                 description=_(u'help_creation_date',
00188                               default=u'Date this object was created'),
00189                 visible={'edit':'invisible', 'view':'invisible'}),
00190         ),
00191         DateTimeField(
00192             'modification_date',
00193             accessor='modified',
00194             mutator = 'setModificationDate',
00195             default_method=DateTime,
00196             languageIndependent=True,
00197             isMetadata=True,
00198             schemata='metadata',
00199             generateMode='mVc',
00200             widget=CalendarWidget(
00201                 label=_(u'label_modification_date',
00202                         default=u'Modification Date'),
00203                 description=_(u'help_modification_date',
00204                               default=u'Date this content was modified last'),
00205                 visible={'edit':'invisible', 'view':'invisible'}),
00206         ),
00207         ))
00208 
00209     def __init__(self):
00210         pass
00211 
00212     security.declarePrivate('defaultLanguage')
00213     def defaultLanguage(self):
00214         """Retrieve the default language"""
00215         return config.LANGUAGE_DEFAULT
00216     
00217     security.declarePrivate('defaultRights')
00218     def defaultRights(self):
00219         """Retrieve the default rights"""
00220         mdtool = getToolByName(self, 'portal_metadata', None)
00221         if mdtool is None:
00222             return ''
00223         for sid, schema in mdtool.listSchemas():
00224             for pid, policy in schema.listPolicies(typ=self.Type()):
00225                 if pid != 'Rights' and not policy.supply_default:
00226                     continue
00227                 return policy.default_value                    
00228         return ''
00229 
00230     security.declareProtected(permissions.View, 'isDiscussable')
00231     def isDiscussable(self, encoding=None):
00232         # Returns either True or False
00233         dtool = getToolByName(self, 'portal_discussion')
00234         return dtool.isDiscussionAllowedFor(self)
00235 
00236     security.declareProtected(permissions.View, 'editIsDiscussable')
00237     def editIsDiscussable(self, encoding=None):
00238         # Returns True, False or if None the default value
00239         result = self.rawIsDiscussable()
00240         if result is not None:
00241             return result
00242         default = self.defaultIsDiscussable()
00243         return default
00244 
00245     security.declareProtected(permissions.View, 'rawIsDiscussable')
00246     def rawIsDiscussable(self):
00247         # Returns True, False or None where None means use the default
00248         result = getattr(aq_base(self), 'allow_discussion', None)
00249         if result is not None:
00250             result = bool(result)
00251         return result
00252 
00253     security.declareProtected(permissions.View, 'defaultIsDiscussable')
00254     def defaultIsDiscussable(self):
00255         # Returns the default value, either True or False
00256         default = None
00257         typeInfo = self.getTypeInfo()
00258         if typeInfo:
00259             default = typeInfo.allowDiscussion()
00260         return default
00261 
00262     security.declareProtected(permissions.ModifyPortalContent,
00263                               'allowDiscussion')
00264     def allowDiscussion(self, allowDiscussion=None, **kw):
00265         default = self.defaultIsDiscussable()
00266         current = self.rawIsDiscussable()
00267 
00268         # If we already overwrote the default or the value we try to set is
00269         # not the default we change it. Otherwise we keep what's there.
00270         if (current is not None or
00271             (current is None and default != allowDiscussion)):
00272             dtool = getToolByName(self, 'portal_discussion', None)
00273             try:
00274                 if dtool is not None:
00275                     try:
00276                         dtool.overrideDiscussionFor(self, allowDiscussion)
00277                     except AttributeError:
00278                         # CMF 2.1.0's CMFDefault.DiscussionTool
00279                         # has tried to delete the class attribute.
00280                         # TODO: remove this when we move to a later
00281                         # CMF.
00282                         pass
00283             except ("Unauthorized", Unauthorized):
00284                 # Catch Unauthorized exception that could be raised by the
00285                 # discussion tool when the authenticated users hasn't
00286                 # ModifyPortalContent permissions.
00287                 # Explanation:
00288                 # A user might have CreatePortalContent but not ModifyPortalContent
00289                 # so allowDiscussion could raise a Unauthorized error although it's
00290                 # called from trusted code. That is VERY bad inside setDefault()!
00291                 log('Catched Unauthorized on discussiontool.' \
00292                     'overrideDiscussionFor(%s)' % self.absolute_url(1),
00293                     level=DEBUG)
00294 
00295     # Vocabulary methods ######################################################
00296 
00297     security.declareProtected(permissions.View, 'languages')
00298     def languages(self):
00299         """Vocabulary method for the language field
00300         """
00301         util = None
00302         # Try the utility first
00303         if HAS_PLONE_I18N:
00304             util = queryUtility(IMetadataLanguageAvailability)
00305         # Fall back to acquiring availableLanguages
00306         if util is None:
00307             languages = getattr(self, 'availableLanguages', None)
00308             if callable(languages):
00309                 languages = languages()
00310             # Fall back to static definition
00311             if languages is None:
00312                 return DisplayList(
00313                     (('en','English'), ('fr','French'), ('es','Spanish'),
00314                      ('pt','Portuguese'), ('ru','Russian')))
00315         else:
00316             languages = util.getLanguageListing()
00317             languages.sort(lambda x,y:cmp(x[1], y[1]))
00318             # Put language neutral at the top.
00319             languages.insert(0,(u'',_(u'Language neutral (site default)')))
00320         return DisplayList(languages)
00321 
00322     #  DublinCore interface query methods #####################################
00323 
00324     security.declareProtected(permissions.View, 'CreationDate')
00325     def CreationDate(self, zone=None):
00326         """ Dublin Core element - date resource created.
00327         """
00328         if zone is None:
00329             zone = _zone
00330         creation = self.getField('creation_date').get(self)
00331         # return unknown if never set properly
00332         return creation is None and 'Unknown' or creation.toZone(zone).ISO()
00333 
00334     security.declareProtected( permissions.View, 'EffectiveDate')
00335     def EffectiveDate(self, zone=None):
00336         """ Dublin Core element - date resource becomes effective.
00337         """
00338         if zone is None:
00339             zone = _zone
00340         effective = self.getField('effectiveDate').get(self)
00341         return effective is None and 'None' or effective.toZone(zone).ISO()
00342 
00343     def _effective_date(self):
00344         """Computed attribute accessor
00345         """
00346         return self.getField('effectiveDate').get(self)
00347 
00348     security.declareProtected(permissions.View, 'effective_date')
00349     effective_date = ComputedAttribute(_effective_date, 1)
00350 
00351 
00352     security.declareProtected( permissions.View, 'ExpirationDate')
00353     def ExpirationDate(self, zone=None):
00354         """Dublin Core element - date resource expires.
00355         """
00356         if zone is None:
00357             zone = _zone
00358         expires = self.getField('expirationDate').get(self)
00359         return expires is None and 'None' or expires.toZone(zone).ISO()
00360 
00361     def _expiration_date(self):
00362         """Computed attribute accessor
00363         """
00364         return self.getField('expirationDate').get(self)
00365 
00366     security.declareProtected(permissions.View, 'expiration_date')
00367     expiration_date = ComputedAttribute(_expiration_date, 1)
00368 
00369     security.declareProtected(permissions.View, 'Date')
00370     def Date(self, zone=None):
00371         """
00372         Dublin Core element - default date
00373         """
00374         # Return effective_date if specifically set, modification date
00375         # otherwise
00376         if zone is None:
00377             zone = _zone
00378         effective = self.getField('effectiveDate').get(self)
00379         if effective is None:
00380             effective = self.modified()
00381         return (effective is None and DateTime().toZone(zone) or
00382                 effective.toZone(zone).ISO())
00383 
00384     security.declareProtected(permissions.View, 'Format')
00385     def Format(self):
00386         """cmf/backward compat
00387         Dublin Core element - resource format
00388         """
00389         # FIXME: get content type from marshaller
00390         return self.getContentType()
00391 
00392     security.declareProtected(permissions.ModifyPortalContent,
00393                               'setFormat')
00394     def setFormat(self, value):
00395         """cmf/backward compat: ignore setFormat"""
00396         self.setContentType(value)
00397 
00398     def Identifer(self):
00399         """ dublin core getId method"""
00400         return self.getId()
00401 
00402     #  DublinCore utility methods #############################################
00403 
00404     security.declareProtected(permissions.View, 'contentEffective')
00405     def contentEffective(self, date):
00406         """Is the date within the resource's effective range?
00407         """
00408         effective = self.getField('effectiveDate').get(self)
00409         expires = self.getField('expirationDate').get(self)
00410         pastEffective = ( effective is None or effective <= date )
00411         beforeExpiration = ( expires is None or expires >= date )
00412         return pastEffective and beforeExpiration
00413 
00414     security.declareProtected(permissions.View, 'contentExpired')
00415     def contentExpired(self, date=None):
00416         """ Is the date after resource's expiration """
00417         if not date:
00418             date = DateTime()
00419         expires = self.getField('expirationDate').get(self)
00420         if not expires:
00421             expires = CEILING_DATE
00422         return expires <= date
00423 
00424     #  CatalogableDublinCore methods ##########################################
00425 
00426     security.declareProtected(permissions.View, 'created')
00427     def created(self):
00428         """Dublin Core element - date resource created,
00429         returned as DateTime.
00430         """
00431         # allow for non-existent creation_date, existed always
00432         created = self.getField('creation_date').get(self)
00433         return created is None and FLOOR_DATE or created
00434 
00435     security.declareProtected(permissions.View, 'modified')
00436     def modified(self):
00437         """Dublin Core element - date resource last modified,
00438         returned as DateTime.
00439         """
00440         modified = self.getField('modification_date').get(self)
00441         # TODO may return None
00442         return modified
00443 
00444     security.declareProtected(permissions.View, 'effective')
00445     def effective(self):
00446         """Dublin Core element - date resource becomes effective,
00447         returned as DateTime.
00448         """
00449         effective = self.getField('effectiveDate').get(self)
00450         return effective is None and FLOOR_DATE or effective
00451 
00452     security.declareProtected(permissions.View, 'expires')
00453     def expires(self):
00454         """Dublin Core element - date resource expires,
00455         returned as DateTime.
00456         """
00457         expires = self.getField('expirationDate').get(self)
00458         return expires is None and CEILING_DATE or expires
00459 
00460     ## code below come from CMFDefault.DublinCore.DefaultDublinCoreImpl #######
00461 
00462     ###########################################################################
00463     #
00464     # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved
00465     #
00466     # This software is subject to the provisions of the Zope Public License,
00467     # Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
00468     # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00469     # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00470     # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00471     # FOR A PARTICULAR PURPOSE
00472     #
00473     ###########################################################################
00474 
00475     #
00476     #  Set-modification-date-related methods.
00477     #  In DefaultDublinCoreImpl for lack of a better place.
00478     #
00479 
00480     security.declareProtected(permissions.ModifyPortalContent,
00481                               'notifyModified')
00482     def notifyModified(self):
00483         """
00484         Take appropriate action after the resource has been modified.
00485         For now, change the modification_date.
00486         """
00487         self.setModificationDate(DateTime())
00488         if shasattr(self, 'http__refreshEtag'):
00489             self.http__refreshEtag()
00490 
00491     security.declareProtected(permissions.ManagePortal,
00492                               'setModificationDate')
00493     def setModificationDate(self, modification_date=None):
00494         """Set the date when the resource was last modified.
00495         When called without an argument, sets the date to now.
00496         """
00497         if modification_date is None:
00498             modified = DateTime()
00499         else:
00500             modified = self._datify(modification_date)
00501         self.getField('modification_date').set(self, modified)
00502 
00503     security.declareProtected(permissions.ManagePortal,
00504                               'setCreationDate')
00505     def setCreationDate(self, creation_date=None):
00506         """Set the date when the resource was created.
00507         When called without an argument, sets the date to now.
00508         """
00509         if creation_date is None:
00510             created = DateTime()
00511         else:
00512             created = self._datify(creation_date)
00513         self.getField('creation_date').set(self, created)
00514 
00515     security.declarePrivate( '_datify' )
00516     def _datify(self, date):
00517         """Try to convert something into a DateTime instance or None
00518         """
00519         # stupid web
00520         if date == 'None':
00521             date = None
00522         if not isinstance(date, DateTime):
00523             if date is not None:
00524                 date = DateTime(date)
00525         return date
00526 
00527     #
00528     #  DublinCore interface query methods
00529     #
00530     security.declareProtected(permissions.View, 'Publisher')
00531     def Publisher(self):
00532         """Dublin Core element - resource publisher
00533         """
00534         # XXX: fixme using 'portal_metadata'
00535         return 'No publisher'
00536 
00537     security.declareProtected(permissions.View, 'ModificationDate')
00538     def ModificationDate(self, zone=None):
00539         """ Dublin Core element - date resource last modified.
00540         """
00541         if zone is None:
00542             zone = _zone
00543         modified = self.modified()
00544         return (modified is None and DateTime().toZone(zone)
00545                 or modified.toZone(zone).ISO())
00546 
00547     security.declareProtected(permissions.View, 'Type')
00548     def Type(self):
00549         """Dublin Core element - Object type"""
00550         if hasattr(aq_base(self), 'getTypeInfo'):
00551             ti = self.getTypeInfo()
00552             if ti is not None:
00553                 return ti.Title()
00554         return self.meta_type
00555 
00556     security.declareProtected(permissions.View, 'Identifier')
00557     def Identifier(self):
00558         """Dublin Core element - Object ID"""
00559         # XXX: fixme using 'portal_metadata' (we need to prepend the
00560         #      right prefix to self.getPhysicalPath().
00561         return self.absolute_url()
00562 
00563     security.declareProtected(permissions.View, 'listContributors')
00564     def listContributors(self):
00565         """Dublin Core element - Contributors"""
00566         return self.Contributors()
00567 
00568     security.declareProtected(permissions.ModifyPortalContent,
00569                               'addCreator')
00570     def addCreator(self, creator=None):
00571         """ Add creator to Dublin Core creators.
00572         """
00573         if creator is None:
00574             mtool = getToolByName(self, 'portal_membership')
00575             creator = mtool.getAuthenticatedMember().getId()
00576 
00577         # call self.listCreators() to make sure self.creators exists
00578         curr_creators = self.listCreators()
00579         if creator and not creator in curr_creators:
00580             self.setCreators(curr_creators + (creator, ))
00581 
00582     security.declareProtected(permissions.View, 'listCreators')
00583     def listCreators(self):
00584         """ List Dublin Core Creator elements - resource authors.
00585         """
00586         creators = self.Schema()['creators']
00587         if not creators.get(self):
00588             # for content created with CMF versions before 1.5
00589             owner_id = self.getOwnerTuple()[1]
00590             if owner_id:
00591                 creators.set(self, (owner_id,))
00592             else:
00593                 creators.set(self, ())
00594 
00595         return creators.get(self)
00596 
00597     security.declareProtected(permissions.View, 'Creator')
00598     def Creator(self):
00599         """ Dublin Core Creator element - resource author.
00600         """
00601         creators = self.listCreators()
00602         return creators and creators[0] or ''
00603 
00604     #
00605     #  DublinCore utility methods
00606     #
00607 
00608     # Deliberately *not* protected by a security declaration
00609     # See https://dev.plone.org/archetypes/ticket/712
00610     def content_type(self):
00611         """ WebDAV needs this to do the Right Thing (TM).
00612         """
00613         return self.Format()
00614     #
00615     #  CatalogableDublinCore methods
00616     #
00617 
00618     security.declareProtected(permissions.View, 'getMetadataHeaders')
00619     def getMetadataHeaders(self):
00620         """ Return RFC-822-style headers.
00621         """
00622         hdrlist = []
00623         hdrlist.append( ( 'Title', self.Title() ) )
00624         hdrlist.append( ( 'Subject', string.join( self.Subject(), ', ' ) ) )
00625         hdrlist.append( ( 'Publisher', self.Publisher() ) )
00626         hdrlist.append( ( 'Description', self.Description() ) )
00627         hdrlist.append( ( 'Contributors', string.join(
00628             self.Contributors(), '; ' ) ) )
00629         hdrlist.append( ( 'Creators', string.join(
00630             self.Creators(), '; ' ) ) )
00631         hdrlist.append( ( 'Effective_date', self.EffectiveDate() ) )
00632         hdrlist.append( ( 'Expiration_date', self.ExpirationDate() ) )
00633         hdrlist.append( ( 'Type', self.Type() ) )
00634         hdrlist.append( ( 'Format', self.Format() ) )
00635         hdrlist.append( ( 'Language', self.Language() ) )
00636         hdrlist.append( ( 'Rights', self.Rights() ) )
00637         return hdrlist
00638 
00639     #
00640     #  Management tab methods
00641     #
00642 
00643     security.declarePrivate( '_editMetadata' )
00644     def _editMetadata(self
00645                       , title=_marker
00646                       , subject=_marker
00647                       , description=_marker
00648                       , contributors=_marker
00649                       , effective_date=_marker
00650                       , expiration_date=_marker
00651                       , format=_marker
00652                       , language=_marker
00653                       , rights=_marker
00654                       ):
00655         """ Update the editable metadata for this resource.
00656         """
00657         if title is not _marker:
00658             self.setTitle( title )
00659         if subject is not _marker:
00660             self.setSubject( subject )
00661         if description is not _marker:
00662             self.setDescription( description )
00663         if contributors is not _marker:
00664             self.setContributors( contributors )
00665         if effective_date is not _marker:
00666             self.setEffectiveDate( effective_date )
00667         if expiration_date is not _marker:
00668             self.setExpirationDate( expiration_date )
00669         if format is not _marker:
00670             self.setFormat( format )
00671         if language is not _marker:
00672             self.setLanguage( language )
00673         if rights is not _marker:
00674             self.setRights( rights )
00675 
00676     security.declareProtected(permissions.ModifyPortalContent,
00677                               'manage_metadata' )
00678     manage_metadata = DTMLFile('zmi_metadata', _dtmldir)
00679 
00680     security.declareProtected(permissions.ModifyPortalContent,
00681                                'manage_editMetadata')
00682     def manage_editMetadata( self
00683                            , title
00684                            , subject
00685                            , description
00686                            , contributors
00687                            , effective_date
00688                            , expiration_date
00689                            , format
00690                            , language
00691                            , rights
00692                            , REQUEST
00693                            ):
00694         """ Update metadata from the ZMI.
00695         """
00696         self._editMetadata( title, subject, description, contributors
00697                           , effective_date, expiration_date
00698                           , format, language, rights
00699                           )
00700         REQUEST[ 'RESPONSE' ].redirect( self.absolute_url()
00701                                 + '/manage_metadata'
00702                                 + '?manage_tabs_message=Metadata+updated.' )
00703 
00704     security.declareProtected(permissions.ModifyPortalContent,
00705                               'editMetadata')
00706     def editMetadata(self
00707                      , title=''
00708                      , subject=()
00709                      , description=''
00710                      , contributors=()
00711                      , effective_date=None
00712                      , expiration_date=None
00713                      , format='text/html'
00714                      , language='en-US'
00715                      , rights=''
00716                      ):
00717         """
00718         used to be:  editMetadata = WorkflowAction(_editMetadata)
00719         Need to add check for webDAV locked resource for TTW methods.
00720         """
00721         self.failIfLocked()
00722         self._editMetadata(title=title
00723                            , subject=subject
00724                            , description=description
00725                            , contributors=contributors
00726                            , effective_date=effective_date
00727                            , expiration_date=expiration_date
00728                            , format=format
00729                            , language=language
00730                            , rights=rights
00731                            )
00732         self.reindexObject()
00733 
00734 InitializeClass(ExtensibleMetadata)
00735 
00736 ExtensibleMetadataSchema = ExtensibleMetadata.schema
00737 
00738 __all__ = ('ExtensibleMetadata', 'ExtensibleMetadataSchema', )