Ticket #119 (assigned enhancement)
More flexible NavFromSitemap component
| Reported by: | svenfuchs@… | Owned by: | argh@… |
|---|---|---|---|
| Priority: | low | Milestone: | |
| Component: | Components | Version: | devel |
| Severity: | normal | Keywords: | |
| Cc: |
Description
Playing around with patPortal to use it for a simple page layout, I've found NavFromSitemap? a bit inflexible and done a ExtNavFromSitemap? component. Differences are:
- added a parameter 'templateName' so that the component can be used more than once per page (I ran into "template already exists" like errors here)
- added a parameter 'recurse' (defaults to true) to enable the user to switch off recursive/treelike building
- added a parameter 'bubbleActive' (defaults to false) so that in a path.subPath.subSubPath path and subPath will also be "active" when the current page is subSubPath
- added a parameter 'path' that enables the user to render a subtree of the entire sitemap.
This way, I can use the same component for displaying a (e.g.) horizontal menu that only shows the topmost level of the sitemap hierarchie and a vertical menu that shows a second level portion of the sitemap.
class patPortal_Component_ExtNavFromSitemap extends patPortal_Component {
public function render( $area, patPortal_Request $request, patPortal_Response
$response )
{
$name = (isset($this->paramstemplateName?) ? $this->paramstemplateName?
: 'NavFromSitemap?');
if (isset($this->paramspath?)) {
$pages = $this->sitemap->loadPage($this->paramspath?);
} else {
$pages = $this->sitemap;
}
$this->tmpl->readTemplatesFromInput( $this->paramstemplate? );
$this->renderNavigation( $request->getPath(), $pages );
return $this->tmpl->getParsedTemplate( $name );
}
private function renderNavigation( $currentPath, $pages, $level = 0 ) {
$name = (isset($this->paramstemplateName?) ? $this->paramstemplateName?
: 'NavFromSitemap?');
$recurse = (isset($this->paramsrecurse?) ? $this->paramsrecurse? : true); $bubbleActive = (isset($this->paramsbubbleActive?) ?
$this->paramsbubbleActive? : false);
$entries = 0;
$nextLevel = $level + 1; foreach( $pages as $page ) {
++$entries;
if( $this->tmpl->exists( $name . '_Container_'.$nextLevel ) )
{
$this->tmpl->clearTemplate( $name . '_Container_'.$nextLevel, true ); $subEntries = 0;
if ($page->isInPath($currentPath) $this->paramsautoCollapse? === false) { if( $recurse AND $page->hasPages() ) {
$subEntries = $this->renderNavigation( $currentPath, $page, $nextLevel );
}
} if ($subEntries>0) {
$this->tmpl->setAttribute( $name . '_Container_'.$nextLevel,
'visibility', 'visible' );
} else {
$this->tmpl->setAttribute( $name . '_Container_'.$nextLevel,
'visibility', 'hidden' );
}
} the name of the template that will be used for this entry $template = $name . '_Entry_'.$level;
mark the active page $active = 'no'; if (!$bubbleActive AND $currentPath == $page->path ) {
$active = 'yes';
} elseif ($bubbleActive AND strpos($currentPath . '.', $page->path) === 0) {
$active = 'yes';
}
add needed variables to the template $this->tmpl->addVars( $template, $page->getMeta(), 'META_' ); $this->tmpl->addVar( $template, 'URI', $page->getUri() ); $this->tmpl->addVar( $template, 'PATH', $page->path ); $this->tmpl->addVar( $template, 'TITLE', $page->title ); $this->tmpl->addVar( $template, 'ACTIVE', $active );
$this->tmpl->parseTemplate( $name . '_Entry_'.$level, 'a' );
}
return $entries;
}
}
Because the parameter $path gets set via config, this makes the subtree shown independend from the current top level path. This might apply to some situations while far more typically we'd have the "second level" subtree depending on the current top level path.
+ projects
+ project1 + project2 + project3
+ presentations
+ presentation1 + presentation2 + presentation3
+ about us
with a
<component:param name="recurse" value="false" />
we'd get only the topmost nodes
+ projects + presentations + aboutus
with a
<component:param name="path" value="projects" />
the component would _always_ show the subtree
+ project1 + project2 + project3
It would make sense to invent another parameter $level or so to have the subtree selected sensitively by the current top level path:
public function render(...) {
if (isset($this->paramslevel?)) {
$level = $this->paramslevel?; $path = $request->getPath(); $path = array_slice(explode('.', $path), 0, $level); $path = implode('.', $path); $pages = $this->sitemap->loadPage($path);
} elseif (isset($this->paramspath?)) {
$pages = $this->sitemap->loadPage($this->paramspath?);
} else {
$pages = $this->sitemap;
}
}
Sorry, I haven't had the time to test this. I think, with a
<component:param name="level" value="1" />
that should load the subtree of the current top level path.
For path=projects or path=project[n], we'd get
+ project1 + project2 + project3
For path=presentations or path=presentations.presentation[n], we'd get
+ presentation1 + presentation2 + presentation3
And for path=aboutus the component would show up nothing.
PS: please correct assignments like prio, serverity etc.

Moving this bug to Sebastian...