2508ebcab4a4cd878fd754aae6a9734a828adf6c
[Portfolio.git] / photo.py
1 # -*- coding: utf-8 -*-
2 ############################################################
3 # Copyright © 2005-2008 Benoît PIN <benoit.pin@ensmp.fr> #
4 # Plinn - http://plinn.org #
5 # #
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 ############################################################
11 """ CMFAware Image
12 $Id: photo.py 1202 2009-07-15 08:48:42Z pin $
13 $URL: http://svn.luxia.fr/svn/labo/projects/zope/Portfolio/trunk/photo.py $
14 """
15
16 from Globals import InitializeClass
17 from AccessControl import ClassSecurityInfo
18 from AccessControl.requestmethod import postonly
19 from DateTime import DateTime
20 from Products.CMFCore.permissions import View, AccessContentsInformation, \
21 ModifyPortalContent, ManageProperties, \
22 ReviewPortalContent
23 from permissions import ViewRawImage
24 from zope.component.factory import Factory
25 from zope.interface import implements
26 from webdav.WriteLockInterface import WriteLockInterface as z2IWriteLock
27 from Products.CMFCore.interfaces import IContentish
28 from Products.CMFCore.interfaces.Contentish import Contentish as z2IContentish
29
30 from Products.CMFCore.DynamicType import DynamicType
31 from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
32 from Products.Photo.Photo import Photo as BasePhoto
33 from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
34 from Products.CMFCore.utils import getToolByName
35 from Products.Photo.cache import memoizedmethod
36 from Products.DCWorkflow.utils import modifyRolesForPermission
37 from interfaces import IPhoto
38
39 class Photo(DynamicType, CMFCatalogAware, BasePhoto, DefaultDublinCoreImpl) :
40 """ Photo CMF aware """
41
42 implements(IPhoto, IContentish)
43 __implements__ = (z2IContentish, z2IWriteLock, DynamicType.__implements__)
44
45 meta_type = BasePhoto.meta_type
46 manage_options = BasePhoto.manage_options
47 security = ClassSecurityInfo()
48
49 security.declareProtected(ViewRawImage, 'index_html')
50 security.declareProtected(ViewRawImage, 'getJpegImage')
51
52 def __init__(self, id, title='', file='', content_type='', precondition='', **kw) :
53 BasePhoto.__init__(self, id, title, file, content_type=content_type, precondition=precondition, **kw)
54 self.id = id
55 self.title = title
56
57 now = DateTime()
58 self.creation_date = now
59 self.modification_date = now
60
61 def update_data(self, data, content_type=None) :
62 BasePhoto.update_data(self, data, content_type=content_type)
63 self.reindexObject()
64
65
66 def _getAfterResizingHooks(self) :
67 pim = getToolByName(self, 'portal_image_manipulation')
68 return pim.image.objectValues(['Script (Python)'])
69
70 def _getAfterTilingHooks(self) :
71 pim = getToolByName(self, 'portal_image_manipulation')
72 return pim.tile.objectValues(['Script (Python)'])
73
74 #
75 # Dublin Core interface
76 #
77
78 security.declareProtected(View, 'Title')
79 @memoizedmethod()
80 def Title(self):
81 """ returns dc:title from xmp
82 """
83 photoshopHeadline = self.getXmpValue('photoshop:Headline')
84 dcTitle = self.getXmpValue('dc:title')
85
86 return dcTitle or photoshopHeadline
87
88
89 security.declareProtected(View, 'listCreators')
90 @memoizedmethod()
91 def listCreators(self):
92 """ returns creator from dc:creator from xmp
93 """
94 return self.getXmpValue('dc:creator')
95
96
97 security.declareProtected(View, 'Description')
98 @memoizedmethod()
99 def Description(self) :
100 """ returns dc:description from xmp """
101 return self.getXmpValue('dc:description')
102
103
104 security.declareProtected(View, 'Subject')
105 @memoizedmethod()
106 def Subject(self):
107 """ returns subject from dc:subject from xmp
108 """
109 return self.getXmpValue('dc:subject')
110
111 security.declareProtected(View, 'Rights')
112 @memoizedmethod()
113 def Rights(self):
114 """ returns rights from dc:rights from xmp
115 """
116 return self.getXmpValue('dc:rights')
117
118 security.declareProtected(ModifyPortalContent, 'editMetadata')
119 def editMetadata(self, **kw):
120 """
121 Need to add check for webDAV locked resource for TTW methods.
122 """
123 # as per bug #69, we cant assume they use the webdav
124 # locking interface, and fail gracefully if they dont
125 if hasattr(self, 'failIfLocked'):
126 self.failIfLocked()
127
128 self.setXmpFields(**kw)
129 for name in ('Title', 'listCreators', 'Description', 'Subject', 'Rights') :
130 self._clearCacheFor(name)
131 self.reindexObject()
132
133
134 def _clearCacheFor(self, name) :
135 try :
136 del self._methodResultsCache[name]
137 except KeyError : pass
138
139
140 security.declareProtected(View, 'SearchableText')
141 def SearchableText(self):
142 """ Return textuals metadata"""
143
144 searchable = (self.Title()
145 , self.Description()
146 , ' '.join(self.Subject())
147 , self.getId()
148 , self.Creator())
149 return ' '.join(searchable)
150
151 security.declareProtected(View, 'DateTimeOriginal')
152 @memoizedmethod()
153 def DateTimeOriginal(self) :
154 """ return DateTimeOriginal exif tag value or created """
155 dto = self.getXmpValue('exif:DateTimeOriginal')
156 if dto :
157 return DateTime(dto)
158 else :
159 return self.created()
160
161
162 CreationDate = DefaultDublinCoreImpl.CreationDate
163
164 Format = BasePhoto.getContentType
165
166 security.declareProtected(ReviewPortalContent, 'hideForAnonymous')
167 @postonly
168 def hideForAnonymous(self, REQUEST=None):
169 ' '
170 modifyRolesForPermission(self, View, ( 'Contributor'
171 , 'Downloader'
172 , 'Manager'
173 , 'Owner'
174 , 'Reader')
175 )
176 self._hiddenForAnon = True
177 self.reindexObjectSecurity()
178 self.reindexObject(idxs=['hiddenForAnonymous'])
179
180
181 security.declareProtected(ReviewPortalContent, 'resetHide')
182 @postonly
183 def resetHide(self, REQUEST=None):
184 ' '
185 modifyRolesForPermission(self, View, [])
186 self._hiddenForAnon = False
187 self.reindexObjectSecurity()
188 self.reindexObject(idxs=['hiddenForAnonymous'])
189
190 security.declareProtected(View, 'hiddenForAnonymous')
191 def hiddenForAnonymous(self):
192 return getattr(self, '_hiddenForAnon', False)
193
194
195 # security.declareProtected(AccessContentsInformation, 'position')
196 # def position(self):
197 # " returns position of self in parent container "
198 # parent = self.getParentNode()
199 # position = parent.getObjectPosition(self.getId())
200 # return position
201
202
203 #
204 # SimpleItem interface
205 #
206
207 def title_or_id(self):
208 """Return the title if it is not blank and the id otherwise.
209 """
210 return self.Title().strip() or self.getId()
211
212 def title_and_id(self):
213 """Return the title if it is not blank and the id otherwise.
214
215 If the title is not blank, then the id is included in parens.
216 """
217 title = self.Title()
218 id = self.getId()
219 return title and ("%s (%s)" % (title,id)) or id
220
221
222 InitializeClass(Photo)
223
224 PhotoFactory = Factory(Photo)