############################################################################## # # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ Favorites are references to other objects within the same CMF site. $Id: Favorite.py 36457 2004-08-12 15:07:44Z jens $ """ import urlparse from Globals import InitializeClass from AccessControl import ClassSecurityInfo from Acquisition import aq_base from Products.CMFCore.utils import getToolByName from permissions import View from permissions import ModifyPortalContent from DublinCore import DefaultDublinCoreImpl from Link import Link factory_type_information = ( { 'id' : 'Favorite' , 'meta_type' : 'Favorite' , 'description' : """\ A Favorite is a Link to an intra-portal resource. """ , 'icon' : 'link_icon.gif' , 'product' : 'CMFDefault' , 'factory' : 'addFavorite' , 'immediate_view' : 'metadata_edit_form' , 'aliases' : {'(Default)':'favorite_view', 'view':'favorite_view'} , 'actions' : ( { 'id' : 'view' , 'name' : 'View' , 'action': 'string:${object_url}/favorite_view' , 'permissions' : ( View, ) } , { 'id' : 'edit' , 'name' : 'Edit' , 'action': 'string:${object_url}/link_edit_form' , 'permissions' : ( ModifyPortalContent, ) } , { 'id' : 'metadata' , 'name' : 'Metadata' , 'action': 'string:${object_url}/metadata_edit_form' , 'permissions' : ( ModifyPortalContent, ) } ) } , ) def addFavorite(self, id, title='', remote_url='', description=''): """ Add a Favorite """ portal_url = getToolByName(self, 'portal_url') portal_obj = portal_url.getPortalObject() content_obj = portal_obj.restrictedTraverse( remote_url ) relUrl = portal_url.getRelativeUrl( content_obj ) o=Favorite( id, title, relUrl, description ) self._setObject(id,o) class Favorite( Link ): """ A Favorite (special kind of Link) """ __implements__ = Link.__implements__ # redundant, but explicit meta_type='Favorite' security = ClassSecurityInfo() def __init__( self , id , title='' , remote_url='' , description='' ): DefaultDublinCoreImpl.__init__(self) self.id=id self.title=title self.remote_url=remote_url self.description = description def manage_afterAdd(self, item, container): """Intercept after favorite has beeing added. The tools are not reachable in '__init__' because 'self' is not yet wrapped at this time. That's why the after add hook has to be intercepted. """ # save unique id of favorite self.remote_uid = self._getUidByUrl() # do the usual stuff Link.manage_afterAdd(self, item, container) def _getUidByUrl(self): """Registers and returns the uid of the remote object if the unique id handler tool is available. """ # check for unique id handler tool handler = getToolByName(self, 'portal_uidhandler', None) if handler is None or not hasattr(handler, 'register'): return portal = getToolByName(self, 'portal_url').getPortalObject() obj = portal.restrictedTraverse(self.remote_url) return handler.register(obj) def _getObjectByUid(self): """Registers and returns the uid of the remote object if the unique id handler tool is available. """ # check for unique id handler tool handler = getToolByName(self, 'portal_uidhandler', None) if handler is None or not hasattr(handler, 'queryObject'): return # check for remote uid info on object uid = getattr(aq_base(self), 'remote_uid', None) if uid is None: return return handler.queryObject(uid, None) security.declareProtected(View, 'getRemoteUrl') def getRemoteUrl(self): """ returns the remote URL of the Link """ # try getting the remote object by unique id remote_url = self._getRemoteUrlTheOldWay() remote_obj = self._getObjectByUid() if remote_obj: url = remote_obj.absolute_url() # update the url when changed (avoid unnecessary ZODB writes) if url != remote_url: self.edit(url) return url return remote_url def _getRemoteUrlTheOldWay(self): """Build the url without having taking the uid into account """ portal_url = getToolByName(self, 'portal_url') if self.remote_url: return portal_url() + '/' + self.remote_url else: return portal_url() security.declareProtected(View, 'getIcon') def getIcon(self, relative_to_portal=0): """ Instead of a static icon, like for Link objects, we want to display an icon based on what the Favorite links to. """ try: return self.getObject().getIcon(relative_to_portal) except: return 'p_/broken' security.declareProtected(View, 'getObject') def getObject(self): """ Return the actual object that the Favorite is linking to """ # try getting the remote object by unique id remote_obj = self._getObjectByUid() if remote_obj is not None: return remote_obj portal_url = getToolByName(self, 'portal_url') return portal_url.getPortalObject().restrictedTraverse(self.remote_url) security.declarePrivate('_edit') def _edit( self, remote_url ): """ Edit the Favorite. Unlike Links, Favorites have URLs that are relative to the root of the site. """ # strip off scheme and machine from URL if present tokens = urlparse.urlparse( remote_url, 'http' ) if tokens[1]: # There is a nethost, remove it t=('', '') + tokens[2:] remote_url=urlparse.urlunparse(t) # if URL begins with site URL, remove site URL portal_url = getToolByName(self, 'portal_url').getPortalPath() i = remote_url.find(portal_url) if i==0: remote_url=remote_url[len(portal_url):] # if site is still absolute, make it relative if remote_url[:1]=='/': remote_url=remote_url[1:] self.remote_url=remote_url # save unique id of favorite self.remote_uid = self._getUidByUrl() InitializeClass(Favorite)