X-Git-Url: https://scm.cri.minesparis.psl.eu/git/Portfolio.git/blobdiff_plain/2da869b2b46179d64c05eaac4081226fdbbbc9ff..e73353500c67453ef9663d67eaeee7dd46c358ee:/Products/Portfolio/photo.py diff --git a/Products/Portfolio/photo.py b/Products/Portfolio/photo.py new file mode 100755 index 0000000..f0a76f5 --- /dev/null +++ b/Products/Portfolio/photo.py @@ -0,0 +1,227 @@ +# -*- coding: utf-8 -*- +############################################################ +# Copyright © 2005-2008 Benoît PIN # +# Plinn - http://plinn.org # +# # +# This program is free software; you can redistribute it # +# and/or modify it under the terms of the Creative Commons # +# "Attribution-Noncommercial 2.0 Generic" # +# http://creativecommons.org/licenses/by-nc/2.0/ # +############################################################ +""" CMFAware Image +""" + +from Globals import InitializeClass +from AccessControl import ClassSecurityInfo +from AccessControl.requestmethod import postonly +from DateTime import DateTime +from Products.CMFCore.permissions import View, AccessContentsInformation, \ + ModifyPortalContent, ManageProperties, \ + ReviewPortalContent +from permissions import ViewRawImage +from zope.component.factory import Factory +from zope.interface import implements +from webdav.interfaces import IWriteLock +from Products.CMFCore.interfaces import IContentish +from Products.CMFCore.interfaces import IDynamicType + +from Products.CMFCore.DynamicType import DynamicType +from Products.CMFCore.CMFCatalogAware import CMFCatalogAware +from Products.Photo.Photo import Photo as BasePhoto +from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl +from Products.CMFCore.utils import getToolByName, getUtilityByInterfaceName +from Products.Photo.cache import memoizedmethod +from Products.DCWorkflow.utils import modifyRolesForPermission +from interfaces import IPhoto + +class Photo(DynamicType, CMFCatalogAware, BasePhoto, DefaultDublinCoreImpl) : + """ Photo CMF aware """ + + implements(IPhoto, IContentish, IWriteLock, IDynamicType) + + meta_type = BasePhoto.meta_type + manage_options = BasePhoto.manage_options + security = ClassSecurityInfo() + + security.declareProtected(ViewRawImage, 'index_html') + security.declareProtected(ViewRawImage, 'getJpegImage') + + def __init__(self, id, title='', file='', content_type='', precondition='', **kw) : + DefaultDublinCoreImpl.__init__(self, title=title) + BasePhoto.__init__(self, id, title, file, content_type=content_type, precondition=precondition, **kw) + self.id = id + self.title = title + + now = DateTime() + self.creation_date = now + self.modification_date = now + + def update_data(self, data, content_type=None) : + BasePhoto.update_data(self, data, content_type=content_type) + # update_data can be invoked during construction + # in this case, reindexObject put a parasite catalag entry. + if self.getParentNode() : + self.reindexObject() + + + def _getAfterResizingHooks(self) : + pim = getToolByName(self, 'portal_image_manipulation') + return pim.image.objectValues(['Script (Python)']) + + def _getAfterTilingHooks(self) : + pim = getToolByName(self, 'portal_image_manipulation') + return pim.tile.objectValues(['Script (Python)']) + + # + # Dublin Core interface + # + + security.declareProtected(View, 'Title') + @memoizedmethod() + def Title(self): + """ returns dc:title from xmp + """ + photoshopHeadline = self.getXmpValue('photoshop:Headline') + dcTitle = self.getXmpValue('dc:title') + + return dcTitle or photoshopHeadline + + + security.declareProtected(View, 'listCreators') + @memoizedmethod() + def listCreators(self): + """ returns creator from dc:creator from xmp + """ + return self.getXmpValue('dc:creator') + + + security.declareProtected(View, 'Description') + @memoizedmethod() + def Description(self) : + """ returns dc:description from xmp """ + return self.getXmpValue('dc:description') + + + security.declareProtected(View, 'Subject') + @memoizedmethod() + def Subject(self): + """ returns subject from dc:subject from xmp + """ + return self.getXmpValue('dc:subject') + + security.declareProtected(View, 'Rights') + @memoizedmethod() + def Rights(self): + """ returns rights from dc:rights from xmp + """ + return self.getXmpValue('dc:rights') + + security.declareProtected(ModifyPortalContent, 'editMetadata') + def editMetadata(self, **kw): + """ + Need to add check for webDAV locked resource for TTW methods. + """ + # as per bug #69, we cant assume they use the webdav + # locking interface, and fail gracefully if they dont + if hasattr(self, 'failIfLocked'): + self.failIfLocked() + + self.setXmpFields(**kw) + for name in ('Title', 'listCreators', 'Description', 'Subject', 'Rights') : + self._clearCacheFor(name) + self.reindexObject() + + + def _clearCacheFor(self, name) : + try : + del self._methodResultsCache[name] + except KeyError : pass + + + security.declareProtected(View, 'SearchableText') + def SearchableText(self): + """ Return textuals metadata""" + + searchable = (self.Title() + , self.Description() + , ' '.join(self.Subject()) + , self.getId() + , self.Creator()) + return ' '.join(searchable) + + security.declareProtected(View, 'DateTimeOriginal') + @memoizedmethod() + def DateTimeOriginal(self) : + """ return DateTimeOriginal exif tag value or created """ + dto = self.getXmpValue('exif:DateTimeOriginal') or self.getXmpValue('xmp:CreateDate') + if dto : + return DateTime(dto) + else : + return self.created() + + + CreationDate = DefaultDublinCoreImpl.CreationDate + + Format = BasePhoto.getContentType + + security.declareProtected(ReviewPortalContent, 'hideForAnonymous') + @postonly + def hideForAnonymous(self, REQUEST=None): + ' ' + modifyRolesForPermission(self, View, ( 'Contributor' + , 'Downloader' + , 'Manager' + , 'Owner' + , 'Reader') + ) + self._hiddenForAnon = True + self.reindexObjectSecurity() + self.reindexObject(idxs=['hiddenForAnonymous']) + + + security.declareProtected(ReviewPortalContent, 'resetHide') + @postonly + def resetHide(self, REQUEST=None): + ' ' + modifyRolesForPermission(self, View, []) + self._hiddenForAnon = False + self.reindexObjectSecurity() + self.reindexObject(idxs=['hiddenForAnonymous']) + + security.declareProtected(View, 'hiddenForAnonymous') + def hiddenForAnonymous(self): + return getattr(self, '_hiddenForAnon', False) + + + # + # SimpleItem interface + # + + def title_or_id(self): + """Return the title if it is not blank and the id otherwise. + """ + return self.Title().strip() or self.getId() + + def title_and_id(self): + """Return the title if it is not blank and the id otherwise. + + If the title is not blank, then the id is included in parens. + """ + title = self.Title() + id = self.getId() + return title and ("%s (%s)" % (title,id)) or id + + +InitializeClass(Photo) + +class _PhotoFactory(Factory) : + def __call__(self, *args, **kw): + if not kw.has_key('thumb_height') or not kw.has_key('thumb_width') : + utool = getUtilityByInterfaceName('Products.CMFCore.interfaces.IURLTool') + portal = utool.getPortalObject() + size = portal.getProperty('thumb_size') + kw.update({'thumb_height' : size, 'thumb_width' : size }) + return self._callable(*args, **kw) + + +PhotoFactory = _PhotoFactory(Photo) \ No newline at end of file