Back to index

plone3  3.1.7
navigation.py
Go to the documentation of this file.
00001 from Acquisition import aq_inner
00002 from zope.interface import implements
00003 from zope.component import getMultiAdapter
00004 
00005 from Acquisition import aq_base
00006 from Products.CMFCore.utils import getToolByName
00007 from Products.CMFPlone import utils
00008 from Products.Five import BrowserView
00009 
00010 from Products.CMFPlone.browser.interfaces import INavigationBreadcrumbs
00011 from Products.CMFPlone.browser.interfaces import INavigationTabs
00012 from Products.CMFPlone.browser.interfaces import INavigationTree
00013 from Products.CMFPlone.browser.interfaces import ISiteMap
00014 from Products.CMFPlone.interfaces import IHideFromBreadcrumbs
00015 
00016 from Products.CMFPlone.browser.navtree import NavtreeQueryBuilder, SitemapQueryBuilder
00017 
00018 # Nasty hack to circumvent 'plone' modulealias
00019 import sys
00020 import plone
00021 del sys.modules['Products.CMFPlone.browser.plone']
00022 
00023 from plone.app.layout.navigation.interfaces import INavtreeStrategy
00024 
00025 from plone.app.layout.navigation.root import getNavigationRoot
00026 from plone.app.layout.navigation.navtree import buildFolderTree
00027 
00028 import zope.deferredimport
00029 zope.deferredimport.deprecated(
00030     "It has been moved to plone.app.layout.navigation.defaultpage. " 
00031     "This alias will be removed in Plone 4.0",
00032     DefaultPage = 'plone.app.layout.navigation.defaultpage:DefaultPage',
00033     )
00034     
00035 import ploneview
00036 sys.modules['Products.CMFPlone.browser.plone'] = ploneview
00037 
00038 def get_url(item):
00039     if hasattr(aq_base(item), 'getURL'):
00040         # Looks like a brain
00041         return item.getURL()
00042     return item.absolute_url()
00043 
00044 def get_id(item):
00045     getId = getattr(item, 'getId')
00046     if not utils.safe_callable(getId):
00047         # Looks like a brain
00048         return getId
00049     return getId()
00050 
00051 def get_view_url(context):
00052     props = getToolByName(context, 'portal_properties')
00053     stp = props.site_properties
00054     view_action_types = stp.getProperty('typesUseViewActionInListings', ())
00055 
00056     item_url = get_url(context)
00057     name = get_id(context)
00058 
00059     if context.portal_type in view_action_types:
00060         item_url += '/view'
00061         name += '/view'
00062 
00063     return name, item_url
00064 
00065 class CatalogNavigationTree(BrowserView):
00066     implements(INavigationTree)
00067 
00068     def navigationTreeRootPath(self):
00069         context = aq_inner(self.context)
00070 
00071         portal_properties = getToolByName(context, 'portal_properties')
00072         portal_url = getToolByName(context, 'portal_url')
00073 
00074         navtree_properties = getattr(portal_properties, 'navtree_properties')
00075 
00076         currentFolderOnlyInNavtree = navtree_properties.getProperty('currentFolderOnlyInNavtree', False)
00077         if currentFolderOnlyInNavtree:
00078             if context.is_folderish():
00079                 return '/'.join(context.getPhysicalPath())
00080             else:
00081                 return '/'.join(utils.parent(context).getPhysicalPath())
00082 
00083         rootPath = getNavigationRoot(context)
00084 
00085         # Adjust for topLevel
00086         topLevel = navtree_properties.getProperty('topLevel', None)
00087         if topLevel is not None and topLevel > 0:
00088             contextPath = '/'.join(context.getPhysicalPath())
00089             if not contextPath.startswith(rootPath):
00090                 return None
00091             contextSubPathElements = contextPath[len(rootPath)+1:].split('/')
00092             if len(contextSubPathElements) < topLevel:
00093                 return None
00094             rootPath = rootPath + '/' + '/'.join(contextSubPathElements[:topLevel])
00095 
00096         return rootPath
00097 
00098     def navigationTree(self):
00099         context = aq_inner(self.context)
00100 
00101         queryBuilder = NavtreeQueryBuilder(context)
00102         query = queryBuilder()
00103 
00104         strategy = getMultiAdapter((context, self), INavtreeStrategy)
00105 
00106         return buildFolderTree(context, obj=context, query=query, strategy=strategy)
00107 
00108 class CatalogSiteMap(BrowserView):
00109     implements(ISiteMap)
00110 
00111     def siteMap(self):
00112         context = aq_inner(self.context)
00113 
00114         queryBuilder = SitemapQueryBuilder(context)
00115         query = queryBuilder()
00116 
00117         strategy = getMultiAdapter((context, self), INavtreeStrategy)
00118 
00119         return buildFolderTree(context, obj=context, query=query, strategy=strategy)
00120 
00121 
00122 class CatalogNavigationTabs(BrowserView):
00123     implements(INavigationTabs)
00124 
00125     def topLevelTabs(self, actions=None, category='portal_tabs'):
00126         context = aq_inner(self.context)
00127 
00128         portal_catalog = getToolByName(context, 'portal_catalog')
00129         portal_properties = getToolByName(context, 'portal_properties')
00130         navtree_properties = getattr(portal_properties, 'navtree_properties')
00131         site_properties = getattr(portal_properties, 'site_properties')
00132 
00133         # Build result dict
00134         result = []
00135         # first the actions
00136         if actions is not None:
00137             for actionInfo in actions.get(category, []):
00138                 data = actionInfo.copy()
00139                 data['name'] = data['title']
00140                 result.append(data)
00141 
00142         # check whether we only want actions
00143         if site_properties.getProperty('disable_folder_sections', False):
00144             return result
00145 
00146         customQuery = getattr(context, 'getCustomNavQuery', False)
00147         if customQuery is not None and utils.safe_callable(customQuery):
00148             query = customQuery()
00149         else:
00150             query = {}
00151 
00152         rootPath = getNavigationRoot(context)
00153         query['path'] = {'query' : rootPath, 'depth' : 1}
00154 
00155         query['portal_type'] = utils.typesToList(context)
00156 
00157         sortAttribute = navtree_properties.getProperty('sortAttribute', None)
00158         if sortAttribute is not None:
00159             query['sort_on'] = sortAttribute
00160 
00161             sortOrder = navtree_properties.getProperty('sortOrder', None)
00162             if sortOrder is not None:
00163                 query['sort_order'] = sortOrder
00164 
00165         if navtree_properties.getProperty('enable_wf_state_filtering', False):
00166             query['review_state'] = navtree_properties.getProperty('wf_states_to_show', [])
00167 
00168         query['is_default_page'] = False
00169         
00170         if site_properties.getProperty('disable_nonfolderish_sections', False):
00171             query['is_folderish'] = True
00172 
00173         # Get ids not to list and make a dict to make the search fast
00174         idsNotToList = navtree_properties.getProperty('idsNotToList', ())
00175         excludedIds = {}
00176         for id in idsNotToList:
00177             excludedIds[id]=1
00178 
00179         rawresult = portal_catalog.searchResults(**query)
00180 
00181         # now add the content to results
00182         for item in rawresult:
00183             if not (excludedIds.has_key(item.getId) or item.exclude_from_nav):
00184                 id, item_url = get_view_url(item)
00185                 data = {'name'      : utils.pretty_title_or_id(context, item),
00186                         'id'         : id,
00187                         'url'        : item_url,
00188                         'description': item.Description}
00189                 result.append(data)
00190         return result
00191 
00192 
00193 class CatalogNavigationBreadcrumbs(BrowserView):
00194     implements(INavigationBreadcrumbs)
00195 
00196     def breadcrumbs(self):
00197         context = aq_inner(self.context)
00198         request = self.request
00199         ct = getToolByName(context, 'portal_catalog')
00200         query = {}
00201 
00202         # Check to see if the current page is a folder default view, if so
00203         # get breadcrumbs from the parent folder
00204         if utils.isDefaultPage(context, request):
00205             currentPath = '/'.join(utils.parent(context).getPhysicalPath())
00206         else:
00207             currentPath = '/'.join(context.getPhysicalPath())
00208         query['path'] = {'query':currentPath, 'navtree':1, 'depth': 0}
00209 
00210         rawresult = ct(**query)
00211 
00212         # Sort items on path length
00213         dec_result = [(len(r.getPath()),r) for r in rawresult]
00214         dec_result.sort()
00215 
00216         rootPath = getNavigationRoot(context)
00217 
00218         # Build result dict
00219         result = []
00220         for r_tuple in dec_result:
00221             item = r_tuple[1]
00222 
00223             # Don't include it if it would be above the navigation root
00224             itemPath = item.getPath()
00225             if rootPath.startswith(itemPath):
00226                 continue
00227 
00228             id, item_url = get_view_url(item)
00229             data = {'Title': utils.pretty_title_or_id(context, item),
00230                     'absolute_url': item_url}
00231             result.append(data)
00232         return result
00233 
00234 
00235 class PhysicalNavigationBreadcrumbs(BrowserView):
00236     implements(INavigationBreadcrumbs)
00237 
00238     def breadcrumbs(self):
00239         context = aq_inner(self.context)
00240         request = self.request
00241         container = utils.parent(context)
00242 
00243         try:
00244             name, item_url = get_view_url(context)
00245         except AttributeError:
00246             print context
00247             raise
00248 
00249         if container is None:
00250             return ({'absolute_url': item_url,
00251                      'Title': utils.pretty_title_or_id(context, context),
00252                     },)
00253 
00254         view = getMultiAdapter((container, request), name='breadcrumbs_view')
00255         base = tuple(view.breadcrumbs())
00256 
00257         # Some things want to be hidden from the breadcrumbs
00258         if IHideFromBreadcrumbs.providedBy(context):
00259             return base
00260 
00261         if base:
00262             item_url = '%s/%s' % (base[-1]['absolute_url'], name)
00263 
00264         rootPath = getNavigationRoot(context)
00265         itemPath = '/'.join(context.getPhysicalPath())
00266 
00267         # don't show default pages in breadcrumbs or pages above the navigation root
00268         if not utils.isDefaultPage(context, request) and not rootPath.startswith(itemPath):
00269             base += ({'absolute_url': item_url,
00270                       'Title': utils.pretty_title_or_id(context, context),
00271                      },)
00272 
00273         return base
00274 
00275 
00276 class RootPhysicalNavigationBreadcrumbs(BrowserView):
00277     implements(INavigationBreadcrumbs)
00278 
00279     def breadcrumbs(self):
00280         # XXX Root never gets included, it's hardcoded as 'Home' in
00281         # the template. We will fix and remove the hardcoding and fix
00282         # the tests.
00283         return ()