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