Ticket #119 (assigned enhancement)

Opened 8 years ago

Last modified 8 years ago

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.

Change History

comment:1 Changed 8 years ago by schst@…

  • Owner changed from schst@… to argh@…
  • Component changed from Framework to Components

Moving this bug to Sebastian...

comment:2 Changed 8 years ago by argh@…

  • Status changed from new to assigned

Thanks! that's definitely very nice - I'll add it as an official component when I restructure the navigational components file structure.

Note: See TracTickets for help on using tickets.