Lack of interest $nodeBreadCrumbs usage

This suggestion has been closed automatically because it did not receive enough votes over an extended period of time. If you wish to see this, please search for an open suggestion and, if you don't find any, post a new one.

Jake Bunce

Well-known member
In reference to this problem with my addon:

http://xenforo.com/community/threads/nodes-as-tabs-with-tab-selection.23295/page-10#post-308184

I can't modify $nodeBreadCrumbs in the controller without affecting notices and body classes. This is a request for code changes to enable me to modify the breadcrumbs without affecting anything else.

The problem I see is that $nodeBreadCrumbs is used for more than just breadcrumbs. Each content template uses $nodeBreadCrumbs to define two things:

1) The breadcrumbs (through <xen:navigation> / <xen:breadcrumb>).

2) The body classes (through <xen:container var="$bodyClasses">).

So when I modify $nodeBreadCrumbs for the purpose of removing some breadcrumbs it has the following two unintended effects:

1) It messes up inheritance of notices among nodes. By way of #1, $nodeBreadCrumbs is used by XenForo_Helper_Criteria:pageMatchesCriteria, which in that function exists as $containerData['navigation']. So removing some breadcrumbs can result in a notice not appearing in a child node when it is assigned to a parent node.

2) It removes body classes for those breadcrumbs that I have removed.

The only way I can figure to modify the breadcrumbs without affecting anything else is to re-render the breadcrumbs or container using template events which is less than ideal. Ideally I want to work with the data and not have to hack the templates.

I am open to suggestions. But for the purpose of this report I would suggest that it's inappropriate to use $nodeBreadCrumbs for anything else other than breadcrumbs. Perhaps build another param that is less intended for a specific use, like $ancestors or $nodePath.
 
Upvote 5
This suggestion has been closed. Votes are no longer accepted.
The only way I can figure to modify the breadcrumbs without affecting anything else is to re-render the breadcrumbs or container using template events which is less than ideal.

I have been testing these solutions. Re-rendering the container works well. It only involves data manipulation, no html hacking. But it requires some maneuvering with the listeners to avoid problems of running listeners multiple times:

Code event: template_post_render

Rich (BB code):
	public static function breadCrumbs($templateName, &$content, array &$containerData, XenForo_Template_Abstract $template)
	{
		if ($templateName == 'PAGE_CONTAINER'
		AND $nodeTabId = $template->getParam('nodeTabId')
		AND $navigation = $template->getParam('navigation')
		)
		{
			$foundTabCrumb = 0;
			foreach ($navigation AS $key => $crumb)
			{
				if (!$foundTabCrumb)
				{
					unset($navigation[$key]);
				}

				if (isset($crumb['node_id'])
				AND $crumb['node_id'] == $nodeTabId)
				{
					$foundTabCrumb = 1;
				}
			}

			$template->setParam('navigation', $navigation);
			$template->setParam('nodeTabId', 0);

			// TEMPORARILY REMOVE RELEVANT LISTENERS FOR RE-RENDER
			$listeners = XenForo_CodeEvent::getEventListeners('template_post_render');
			XenForo_CodeEvent::setListeners(array('template_post_render' => false));

			$content = $template->render();

			XenForo_CodeEvent::setListeners(array('template_post_render' => $listeners));
		}
	}

The nodeTabId param is used in removing breadcrumbs and also as a flag to prevent the listener from running again during the re-render. But I also had to add the blue code to prevent other listeners for the same event from running again during the re-render. It's a little complicated but it works. However this maneuvering does require my listener to run first so I set an execution order of 0. It also has the trivial side effect of outputting template errors twice.

So I have a solution now. But this added complexity wouldn't be necessary if $nodeBreadCrumbs wasn't used for other stuff.

Also, while working on re-rendering the container I realized that a template_pre_render event would make this workaround much easier. It would allow me to modify the params before the render and completely avoid the re-render.
 
Even with the above solution I have encountered a conflict with the Ad Manager addon which does criteria checking in the template_post_render event:

http://xenforo.com/community/threads/nodes-as-tabs.26687/page-5#post-352337

The idea behind the above solution was to postpone the breadcrumb changes until after the criteria check is done in the view renderer, since the criteria check depends on the breadcrumb information in the container data. But the Ad Manager addon is doing its own criteria checking in template_post_render which breaks down because I have modified the breadcrumb information on which the criteria check depends, and I cannot possibly make my changes any later in the execution.

So we are back to the original suggestion... don't use $nodeBreadCrumbs for anything else except breadcrumbs. That way I can modify it all the way up in the controller and not have to worry about breaking page criteria or body classes.
 
one year bump :oops:

What about creating an alternate breadcrumb array that is checked by the container? If $altNavigation then use it, else use regular $navigation. That way addons can modify the breadcrumbs by defining $altNavigation in the containerParams. That would fix the problem with minimal changes.

edit - though you would be shortcutting <xen:navigation>/<xen:breadcrumb> which isn't good.
 
Last edited:
Top Bottom