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