1 # -*- coding: utf-8 -*-
2 ############################################################
3 # Copyright © 2005-2008 Benoît PIN <benoit.pin@ensmp.fr> #
4 # Plinn - http://plinn.org #
6 # This program is free software; you can redistribute it #
7 # and/or modify it under the terms of the Creative Commons #
8 # "Attribution-Noncommercial 2.0 Generic" #
9 # http://creativecommons.org/licenses/by-nc/2.0/ #
10 ############################################################
14 from Globals
import InitializeClass
15 from AccessControl
import ClassSecurityInfo
16 from AccessControl
.requestmethod
import postonly
17 from DateTime
import DateTime
18 from Products
.CMFCore
.permissions
import View
, AccessContentsInformation
, \
19 ModifyPortalContent
, ManageProperties
, \
21 from permissions
import ViewRawImage
22 from zope
.component
.factory
import Factory
23 from zope
.interface
import implements
24 from webdav
.interfaces
import IWriteLock
25 from Products
.CMFCore
.interfaces
import IContentish
26 from Products
.CMFCore
.interfaces
import IDynamicType
28 from Products
.CMFCore
.DynamicType
import DynamicType
29 from Products
.CMFCore
.CMFCatalogAware
import CMFCatalogAware
30 from Products
.Photo
.Photo
import Photo
as BasePhoto
31 from Products
.CMFDefault
.DublinCore
import DefaultDublinCoreImpl
32 from Products
.CMFCore
.utils
import getToolByName
, getUtilityByInterfaceName
33 from Products
.Photo
.cache
import memoizedmethod
34 from Products
.DCWorkflow
.utils
import modifyRolesForPermission
35 from interfaces
import IPhoto
37 class Photo(DynamicType
, CMFCatalogAware
, BasePhoto
, DefaultDublinCoreImpl
) :
38 """ Photo CMF aware """
40 implements(IPhoto
, IContentish
, IWriteLock
, IDynamicType
)
42 meta_type
= BasePhoto
.meta_type
43 manage_options
= BasePhoto
.manage_options
44 security
= ClassSecurityInfo()
46 security
.declareProtected(ViewRawImage
, 'index_html')
47 security
.declareProtected(ViewRawImage
, 'getJpegImage')
49 def __init__(self
, id, title
='', file='', content_type
='', precondition
='', **kw
) :
50 DefaultDublinCoreImpl
.__init
__(self
, title
=title
)
51 BasePhoto
.__init
__(self
, id, title
, file, content_type
=content_type
, precondition
=precondition
, **kw
)
56 self
.creation_date
= now
57 self
.modification_date
= now
59 def update_data(self
, data
, content_type
=None) :
60 BasePhoto
.update_data(self
, data
, content_type
=content_type
)
61 # update_data can be invoked during construction
62 # in this case, reindexObject put a parasite catalag entry.
63 if self
.getParentNode() :
67 def _getAfterResizingHooks(self
) :
68 pim
= getToolByName(self
, 'portal_image_manipulation')
69 return pim
.image
.objectValues(['Script (Python)'])
71 def _getAfterTilingHooks(self
) :
72 pim
= getToolByName(self
, 'portal_image_manipulation')
73 return pim
.tile
.objectValues(['Script (Python)'])
76 # Dublin Core interface
79 security
.declareProtected(View
, 'Title')
82 """ returns dc:title from xmp
84 photoshopHeadline
= self
.getXmpValue('photoshop:Headline')
85 dcTitle
= self
.getXmpValue('dc:title')
87 return dcTitle
or photoshopHeadline
90 security
.declareProtected(View
, 'listCreators')
92 def listCreators(self
):
93 """ returns creator from dc:creator from xmp
95 return self
.getXmpValue('dc:creator')
98 security
.declareProtected(View
, 'Description')
100 def Description(self
) :
101 """ returns dc:description from xmp """
102 return self
.getXmpValue('dc:description')
105 security
.declareProtected(View
, 'Subject')
108 """ returns subject from dc:subject from xmp
110 return self
.getXmpValue('dc:subject')
112 security
.declareProtected(View
, 'Rights')
115 """ returns rights from dc:rights from xmp
117 return self
.getXmpValue('dc:rights')
119 security
.declareProtected(ModifyPortalContent
, 'editMetadata')
120 def editMetadata(self
, **kw
):
122 Need to add check for webDAV locked resource for TTW methods.
124 # as per bug #69, we cant assume they use the webdav
125 # locking interface, and fail gracefully if they dont
126 if hasattr(self
, 'failIfLocked'):
129 self
.setXmpFields(**kw
)
130 for name
in ('Title', 'listCreators', 'Description', 'Subject', 'Rights') :
131 self
._clearCacheFor
(name
)
135 def _clearCacheFor(self
, name
) :
137 del self
._methodResultsCache
[name
]
138 except KeyError : pass
141 security
.declareProtected(View
, 'SearchableText')
142 def SearchableText(self
):
143 """ Return textuals metadata"""
145 searchable
= (self
.Title()
147 , ' '.join(self
.Subject())
150 return ' '.join(searchable
)
152 security
.declareProtected(View
, 'DateTimeOriginal')
154 def DateTimeOriginal(self
) :
155 """ return DateTimeOriginal exif tag value or created """
156 dto
= self
.getXmpValue('exif:DateTimeOriginal') or self
.getXmpValue('xmp:CreateDate')
160 return self
.created()
163 CreationDate
= DefaultDublinCoreImpl
.CreationDate
165 Format
= BasePhoto
.getContentType
167 security
.declareProtected(ReviewPortalContent
, 'hideForAnonymous')
169 def hideForAnonymous(self
, REQUEST
=None):
171 modifyRolesForPermission(self
, View
, ( 'Contributor'
177 self
._hiddenForAnon
= True
178 self
.reindexObjectSecurity()
179 self
.reindexObject(idxs
=['hiddenForAnonymous'])
182 security
.declareProtected(ReviewPortalContent
, 'resetHide')
184 def resetHide(self
, REQUEST
=None):
186 modifyRolesForPermission(self
, View
, [])
187 self
._hiddenForAnon
= False
188 self
.reindexObjectSecurity()
189 self
.reindexObject(idxs
=['hiddenForAnonymous'])
191 security
.declareProtected(View
, 'hiddenForAnonymous')
192 def hiddenForAnonymous(self
):
193 return getattr(self
, '_hiddenForAnon', False)
197 # SimpleItem interface
200 def title_or_id(self
):
201 """Return the title if it is not blank and the id otherwise.
203 return self
.Title().strip() or self
.getId()
205 def title_and_id(self
):
206 """Return the title if it is not blank and the id otherwise.
208 If the title is not blank, then the id is included in parens.
212 return title
and ("%s (%s)" % (title
,id)) or id
215 InitializeClass(Photo
)
217 class _PhotoFactory(Factory
) :
218 def __call__(self
, *args
, **kw
):
219 if not kw
.has_key('thumb_height') or not kw
.has_key('thumb_width') :
220 utool
= getUtilityByInterfaceName('Products.CMFCore.interfaces.IURLTool')
221 portal
= utool
.getPortalObject()
222 size
= portal
.getProperty('thumb_size')
223 kw
.update({'thumb_height' : size
, 'thumb_width' : size
})
224 return self
._callable
(*args
, **kw
)
227 PhotoFactory
= _PhotoFactory(Photo
)