5.2.2.
Constructing the navigation tree
Up one level
The navigation tree portlet uses a view, found in CMFPlone.browser.interfaces.INavigationPortlet with a factory in CMFPlone.browser.portlets.navigation. This view in turn uses a more general view, CMFPlone.browser.interfaces.INavigationTree that is implemented in CMFPlone.browser.navigation.CatalogNavigationTree.
Previously, the navigation tree used to be constructed in CMFPlone.PloneTool, and there is still a deprecated createNavTree() method there. A utility method that invokes the view is found in CMFPlone.utils.createNavTree().
The actual construction of the navtree is delegated to a generic function found in CMFPlone.browser.navtree called buildFolderTree(). This function has a single purpose: Execute a catalog query and turn the results into a navigation tree-like structure. It is thus generic, and can be used to construct other navigational structures (such as the TOC for this reference manual).
Because the navigation tree needs to take several properties into account, the navtree builder can take a "strategy" object, which implements CMFPlone.browser.interfaces.INavtreeStrategy. This can provide methods used to decide whether a given node should be included and/or whether a whole subtree should be pruned. It can also decorate the node dicts with additional keys, used to hold domain-specific information.
The standard navigation tree strategy is found in CMFPlone.browser.navtree.DefaultNavtreeStrategy. In fact this extends the sitemap navtree strategy, because a navtree is essentially a more restricted form of a sitemap.
The navtree strategy is an adapter, looked up on the context (the content object being viewed - registered for * by default) and the interface of the view that is constructing it (to distinguish the sitemap from the navtree):
<adapter for="*
.interfaces.INavigationTree"
factory=".navtree.DefaultNavtreeStrategy"
provides=".interfaces.INavtreeStrategy" />
The CatalogNavigationTree class that implements INavigationTree thus does this:
def navigationTree(self):
context = utils.context(self)
queryBuilder = NavtreeQueryBuilder(context)
query = queryBuilder()
strategy = getMultiAdapter((context, self), INavtreeStrategy)
return buildFolderTree(context, obj=context, query=query, strategy=strategy)
The NavtreeQueryBuilder, is found in CMFPlone.browser.navtree, with an interface in CMFPlone.browser.interfaces.INavigationQueryBuilder. This simply wraps up the task of constructing the catalog query dict that is used to build the navtree, so that it may be re-used.
To make it easier to create custom navtrees and similar structures for site integrators, the contents of CMFPlone.browser.navtree may be imported from protected code, by virtue of the following statement in 'CMFPlone/__init__.py':
allow_module('Products.CMFPlone.browser.navtree')
To ensure that the methods and attributes of the query builders and navtree strategies are accessible as well, CMFPlone/browser/configure.zcml contains:
<content class="Products.CMFPlone.Portal.PloneSite">
<implements interface=".interfaces.INavigationRoot" />
</content>
<content class=".navtree.NavtreeStrategyBase">
<allow interface=".interfaces.INavtreeStrategy" />
</content>
<content class=".navtree.NavtreeQueryBuilder">
<allow interface=".interfaces.INavigationQueryBuilder" />
</content>