Back to index

plone3  3.1.7
Event.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 """ Event: A CMF-enabled Event object.
00014 
00015 $Id: Event.py 77186 2007-06-28 19:06:19Z yuppie $
00016 """
00017 
00018 import transaction
00019 from AccessControl import ClassSecurityInfo
00020 from DateTime import DateTime
00021 from Globals import InitializeClass
00022 from zope.component.factory import Factory
00023 from zope.interface import implements
00024 
00025 from Products.CMFCore.PortalContent import PortalContent
00026 from Products.CMFCore.utils import contributorsplitter
00027 from Products.CMFCore.utils import keywordsplitter
00028 from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
00029 from Products.CMFDefault.utils import bodyfinder
00030 from Products.CMFDefault.utils import formatRFC822Headers
00031 from Products.CMFDefault.utils import html_headcheck
00032 from Products.CMFDefault.utils import parseHeadersBody
00033 from Products.CMFDefault.utils import SimpleHTMLParser
00034 from Products.GenericSetup.interfaces import IDAVAware
00035 
00036 from exceptions import ResourceLockedError
00037 from interfaces import IEvent
00038 from interfaces import IMutableEvent
00039 from permissions import ChangeEvents
00040 from permissions import ModifyPortalContent
00041 from permissions import View
00042 
00043 
00044 def addEvent( self
00045             , id
00046             , title=''
00047             , description=''
00048             , effective_date = None 
00049             , expiration_date = None 
00050             , start_date = None 
00051             , end_date = None
00052             , location=''
00053             , contact_name=''
00054             , contact_email=''
00055             , contact_phone=''
00056             , event_url=''
00057             , REQUEST=None
00058             ):
00059     """Create an empty event.
00060     """
00061     event = Event( id
00062                  , title
00063                  , description
00064                  , effective_date
00065                  , expiration_date
00066                  , start_date
00067                  , end_date
00068                  , location
00069                  , contact_name
00070                  , contact_email
00071                  , contact_phone
00072                  , event_url
00073                  )
00074     self._setObject(id, event)
00075 
00076 def _dateStrings( when ):
00077 
00078     strings = {}
00079 
00080     if when is not None:
00081         strings[ 'year' ]   = str( when.year() )
00082         strings[ 'month' ]  = str( when.month() )
00083         strings[ 'day' ]    = str( when.day() )
00084     else:
00085         strings[ 'year' ]   = ''
00086         strings[ 'month' ]  = ''
00087         strings[ 'day' ]    = ''
00088 
00089     return strings
00090 
00091 
00092 class Event(PortalContent, DefaultDublinCoreImpl):
00093 
00094     """Events are objects for the Calendar topical query.
00095     """
00096 
00097     # Declarative security
00098     security = ClassSecurityInfo()
00099     security.declareObjectProtected(View)
00100 
00101     implements(IMutableEvent, IEvent, IDAVAware)
00102     __implements__ = ( PortalContent.__implements__
00103                      , DefaultDublinCoreImpl.__implements__
00104                      )
00105 
00106     def __init__( self
00107                 , id
00108                 , title=''
00109                 , description=''
00110                 , effective_date = None 
00111                 , expiration_date = None 
00112                 , start_date = None
00113                 , end_date = None
00114                 , location=''
00115                 , contact_name=''
00116                 , contact_email=''
00117                 , contact_phone=''
00118                 , event_url=''
00119                 ):
00120         DefaultDublinCoreImpl.__init__(self)
00121         self.id=id
00122         self.setTitle(title)
00123         self.setDescription(description)
00124         self.effective_date = effective_date
00125         self.expiration_date = expiration_date
00126         self.setStartDate(start_date)
00127 
00128         if start_date is None:
00129             start_date = DateTime()
00130         if end_date is None:
00131             end_date = start_date
00132 
00133         if end_date < start_date:
00134             end_date = start_date
00135 
00136         self.setEndDate(end_date)
00137         self.location=location
00138         self.contact_name=contact_name
00139         self.contact_email=contact_email
00140         self.contact_phone=contact_phone
00141         self.event_url=event_url
00142 
00143     security.declarePrivate( '_datify' )
00144     def _datify( self, attrib ):
00145         if attrib == 'None':
00146             attrib = None
00147         elif not isinstance( attrib, DateTime ):
00148             if attrib is not None:
00149                 attrib = DateTime( attrib )
00150         return attrib
00151 
00152     security.declarePublic('getEndStrings')
00153     def getEndStrings(self):
00154         """ Returns a mapping with string representations for the end time
00155 
00156         o keys are 'day', 'month' and 'year'
00157         """
00158         return _dateStrings(self.end())
00159 
00160     security.declarePublic('getStartStrings')
00161     def getStartStrings(self):
00162         """ Returns a mapping with string representations for the start time
00163 
00164         o keys are 'day', 'month' and 'year'
00165         """
00166         return _dateStrings(self.start())
00167 
00168     security.declareProtected(ChangeEvents, 'edit')
00169     def edit( self
00170             , title=None
00171             , description=None
00172             , eventType=None
00173             , effectiveDay=None
00174             , effectiveMo=None
00175             , effectiveYear=None
00176             , expirationDay=None
00177             , expirationMo=None
00178             , expirationYear=None
00179             , start_time=None
00180             , startAMPM=None
00181             , stop_time=None
00182             , stopAMPM=None
00183             , location=None
00184             , contact_name=None
00185             , contact_email=None
00186             , contact_phone=None
00187             , event_url=None
00188             ):
00189         """\
00190         """
00191 
00192         if title is not None: 
00193             self.setTitle(title)
00194         if description is not None:
00195             self.setDescription(description)
00196         if eventType is not None:
00197             self.setSubject(eventType)
00198 
00199         start_date = end_date = None
00200 
00201         if effectiveDay and effectiveMo and effectiveYear and start_time:
00202             efdate = '%s/%s/%s %s %s' % (effectiveYear
00203                                          , effectiveMo
00204                                          , effectiveDay
00205                                          , start_time
00206                                          , startAMPM
00207                                          )
00208             start_date = DateTime( efdate )
00209 
00210         if expirationDay and expirationMo and expirationYear and stop_time:
00211 
00212             exdate = '%s/%s/%s %s %s' % (expirationYear
00213                                          , expirationMo
00214                                          , expirationDay
00215                                          , stop_time
00216                                          , stopAMPM
00217                                          )
00218             end_date = DateTime( exdate )
00219 
00220         if start_date and end_date:
00221 
00222             if end_date < start_date:
00223                 end_date = start_date
00224 
00225             self.setStartDate( start_date )
00226             self.setEndDate( end_date )
00227 
00228         if location is not None:
00229             self.location = location
00230         if contact_name is not None:
00231             self.contact_name = contact_name
00232         if contact_email is not None:
00233             self.contact_email = contact_email
00234         if contact_phone is not None:
00235             self.contact_phone = contact_phone
00236         if event_url is not None:
00237             self.event_url = event_url
00238         self.reindexObject()
00239 
00240     security.declarePublic('buildTimes')
00241     def buildTimes(self):
00242         result = []
00243         for hour in range (1, 13):
00244             for min in (00, 30):
00245                 result.append('%02d:%02d' % (hour, min))
00246         return result
00247 
00248     security.declarePublic('buildDays')
00249     def buildDays(self):
00250         result = []
00251         for day in range (1, 32):
00252             result.append(str('%d' % (day)))
00253         return result
00254 
00255     security.declarePublic('buildMonths')
00256     def buildMonths(self):
00257         result = []
00258         for month in range (1, 13):
00259             result.append(str('%d' % (month)))
00260         return result
00261 
00262     security.declarePublic('buildYears')
00263     def buildYears(self):
00264         result = []
00265         start = (DateTime().year() - 2)
00266         end = (DateTime().year() + 5)
00267         for year in range (start, end):
00268             result.append(str(year))
00269         return result
00270 
00271     security.declareProtected(ChangeEvents, 'setStartDate')
00272     def setStartDate(self, start):
00273         """ Setting the event start date when the event is scheduled to begin.
00274         """
00275         self.start_date = self._datify(start)
00276 
00277     security.declareProtected(ChangeEvents, 'setEndDate')
00278     def setEndDate(self, end):
00279         """ Setting the event end date, when the event ends.
00280         """
00281         self.end_date = self._datify(end)
00282 
00283     security.declarePublic('start')
00284     def start(self):
00285         """ Return our start time as a DateTime object
00286         """
00287         date = getattr( self, 'start_date', None )
00288         return date is None and self.created() or date
00289 
00290     security.declarePublic('end')
00291     def end(self):
00292         """ Return our end time as a DateTime object
00293         """
00294         date = getattr( self, 'end_date', None )
00295         return date is None and self.start() or date
00296 
00297     security.declarePublic('getStartTimeString')
00298     def getStartTimeString( self ):
00299         """ Return our start time as a string.
00300         """
00301         return self.start().AMPMMinutes() 
00302 
00303     security.declarePublic('getStopTimeString')
00304     def getStopTimeString( self ):
00305         """ Return our stop time as a string.
00306         """
00307         return self.end().AMPMMinutes() 
00308 
00309     security.declarePrivate('handleText')
00310     def handleText(self, text, format=None):
00311         """ Handles the raw text, returning headers, body, cooked, format """
00312         headers = {}
00313         if format == 'html':
00314             parser = SimpleHTMLParser()
00315             parser.feed(text)
00316             headers.update(parser.metatags)
00317             if parser.title:
00318                 headers['Title'] = parser.title
00319             bodyfound = bodyfinder(text)
00320             if bodyfound:
00321                 body = bodyfound
00322         else:
00323             headers, body = parseHeadersBody(text, headers)
00324 
00325         return headers, body, format
00326 
00327     security.declareProtected(ModifyPortalContent, 'setMetadata')
00328     def setMetadata(self, headers):
00329         """ Set an Event's metadata
00330 
00331         o headers is a mapping containing keys corresponding to
00332         Dublin Core metadata fields
00333         o Only those attributes that are passed in with the mapping are
00334         manipulated
00335         """
00336         headers['Format'] = self.Format()
00337         new_subject = keywordsplitter(headers)
00338         headers['Subject'] = new_subject or self.Subject()
00339         new_contrib = contributorsplitter(headers)
00340         headers['Contributors'] = new_contrib or self.Contributors()
00341         haveheader = headers.has_key
00342         for key, value in self.getMetadataHeaders():
00343             if not haveheader(key):
00344                 headers[key] = value
00345         self._editMetadata(title=headers['Title'],
00346                           subject=headers['Subject'],
00347                           contributors=headers['Contributors'],
00348                           effective_date=headers['Effective_date'],
00349                           expiration_date=headers['Expiration_date'],
00350                           format=headers['Format'],
00351                           language=headers['Language'],
00352                           rights=headers['Rights'],
00353                           )
00354 
00355     security.declarePublic( 'getMetadataHeaders' )
00356     def getMetadataHeaders(self):
00357         """ Return metadata attributes in RFC-822-style header spec.
00358         """
00359         fmt = '%Y-%m-%d %H:%M:%S'
00360         hdrlist = [x for x in DefaultDublinCoreImpl.getMetadataHeaders(self)
00361                          if x[0] != 'Description']
00362         hdrlist.append(('Startdate', self.start().strftime(fmt)))
00363         hdrlist.append(('Enddate',  self.end().strftime(fmt)))
00364         hdrlist.append(('Location', self.location))
00365         hdrlist.append(('Contactname', self.contact_name))
00366         hdrlist.append(('Contactemail', self.contact_email))
00367         hdrlist.append(('Contactphone', self.contact_phone))
00368         hdrlist.append(('Eventurl', self.event_url))
00369 
00370         return hdrlist
00371 
00372     ## FTP handlers
00373 
00374     security.declareProtected(ModifyPortalContent, 'PUT')
00375     def PUT(self, REQUEST, RESPONSE):
00376         """ Handle HTTP (and presumably FTP?) PUT requests """
00377         self.dav__init(REQUEST, RESPONSE)
00378         self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
00379         body = REQUEST.get('BODY', '')
00380         guessedformat = REQUEST.get_header('Content-Type', 'text/plain')
00381         ishtml = (guessedformat == 'text/html') or html_headcheck(body)
00382 
00383         if ishtml: self.setFormat('text/html')
00384         else: self.setFormat('text/plain')
00385 
00386         try:
00387             headers, body, format = self.handleText(text=body)
00388             self.setMetadata(headers)
00389             self.setStartDate(headers['Startdate'])
00390             self.setEndDate(headers['Enddate'])
00391             self.edit( location=headers['Location']
00392              , contact_name=headers['Contactname']
00393              , contact_email=headers['Contactemail']
00394              , contact_phone=headers['Contactphone']
00395              , event_url=headers['Eventurl']
00396              , description=body
00397              )
00398 
00399         except ResourceLockedError, msg:
00400             transaction.abort()
00401             RESPONSE.setStatus(423)
00402             return RESPONSE
00403 
00404         RESPONSE.setStatus(204)
00405         self.reindexObject()
00406         return RESPONSE
00407 
00408     security.declareProtected(View, 'manage_FTPget')
00409     def manage_FTPget(self):
00410         "Get the document body for FTP download (also used for the WebDAV SRC)"
00411         hdrlist = self.getMetadataHeaders()
00412         hdrtext = formatRFC822Headers( hdrlist )
00413         bodytext = '%s\r\n\r\n%s' % ( hdrtext, self.Description() )
00414 
00415         return bodytext
00416 
00417     security.declareProtected(View, 'get_size')
00418     def get_size( self ):
00419         """ Used for FTP and apparently the ZMI now too """
00420         return len(self.manage_FTPget())
00421 
00422 InitializeClass(Event)
00423 
00424 EventFactory = Factory(Event)