Hardcode several autonav blocks?

Permalink
Hi,

Probably in C5.7 something has changed in a way we hardcode blocks to pages, since after hardcoding several autonav blocks on the same page with different setups I get faulty results. First hardcoded result is displayed correctly, the next ones show doubled / tripled copies of autonav.

Like so:
First hardcoded autonav:
$nav = BlockType::getByHandle('autonav');
$nav->controller->orderBy = 'display_asc';
$nav->controller->displayPages = 'top';
$nav->controller->displaySubPages = 'relevant_breadcrumb';
$nav->controller->displaySubPageLevels = 'enough';
$nav->render();

results: OK - as expected
Second hardcoded autonav:
$nav2 = BlockType::getByHandle('autonav');
$nav2->controller->orderBy = 'display_asc';
$nav2->controller->displayPages = 'current';
$nav2->controller->displaySubPages = 'none';
$nav2->render();

This autonav renders first autonav, and only then spits out the needed autonav.
Third hardcoded autonav, starts again with first two autonavs, and only then displays needed results. In the end I get page filled with repeated results.

Am I doing something wrong or is it some weird bug?

Many thanks in advance for any help!

View Replies:
karladidas replied on at Permalink Reply
karladidas
Hi,

I have just found the exact same issue. So I had a peek in the code and made a little hack/fix:

It appears that the navArray array isn't cleared before for each use of the autonav block, so add:
$this->navArray = array();

to the getNavItems() function in /concrete/blocks/autonav/controller.php (line 142).

This seems to fix the issue, at least for me. I am sure there is a much prettier and extensible way to overload the controller but I don't have the time to work it out.

Cheers.
JohntheFish replied on at Permalink Reply
JohntheFish
Small word of caution. If there are a lot of pages in the nav, repopulating the nav array for every nav on a page could create a performance issue.
karladidas replied on at Permalink Reply
karladidas
Hi John, any ideas on how to fix the issue without clearing this array?
JohntheFish replied on at Permalink Reply
JohntheFish
I would start by making some tests to see if it really does cause a performance issue.

If it is an issue, I would be tempted to try filling the array once with the superset of all nav's on the page, then extract the subset for each nav from that superset.
karladidas replied on at Permalink Reply
karladidas
Hi John, Thanks for the advice. Do you think this should be escalated to a bug? I'm no c5 developer, but it does appear that this is something that was working in 5.6.x but not now in 5.7.x.
karladidas replied on at Permalink Reply
karladidas
Hi gorillabrand,

Actually there is no need to mess with the core code. You can simply do this:

$nav2 = BlockType::getByHandle('autonav');
$nav2->controller->orderBy = 'display_asc';
$nav2->controller->displayPages = 'current';
$nav2->controller->displaySubPages = 'none';
$nav2->controller->navArray = array();
$nav2->render();

I am no C5 dev, but at a quick glance it appears getByHandle seems to return the same autonav object each time, not a new instance. So then when the view runs getNavItems on subsequent calls, it goes through adding the same navItems again. Clearing the navArray before the render stops the duplicates being displayed. There are comments in the core code that say repeating the calls to getNavItems will cause duplicates. So I guess perhaps it is something that is known about? As John says this could cause a performance issue, but as it seems to be running through the whole nav each time it might at least be a quick fix.
A3020 replied on at Permalink Reply
A3020
I'm facing the same problem (http://www.concrete5.org/community/forums/5-7-discussion/database-getrepository-and-blocktypes/).

With your solution you get the right set of pages, but not the right template. If a second nav is using another render(..), it uses the template of the first one.

Any ideas how to solve that?
karladidas replied on at Permalink Reply
karladidas
Have a look at this post:

http://www.concrete5.org/community/forums/5-7-discussion/5.7-blockt...

I had a similar problem and tried this based on kieranrushby's idea:

$nav2 = BlockType::getByHandle('autonav');
$nav2->controller->orderBy = 'display_asc';
$nav2->controller->displayPages = 'current';
$nav2->controller->displaySubPages = 'none';
$nav2->controller->navArray = array();
$nav2->controller->blockViewRenderOverride = 'templates/my_template';
$nav2->render();

Where your template is: /application/blocks/autonav/templates/my_template.php

BUT ... a heads up ... using blockViewRenderOverride will override all following uses of autonav on a page (as they are all the same instance). So you will need to set it back to 'view' if you want to go back to default on following uses.

To be honest I have now stopped hardcoding autonav blocks in 5.7, doing it via the interface doesn't have any of the above issues. Also I have read that hardcoding bypasses the block caching, so you don't get the performance boost of the cache.
A3020 replied on at Permalink Reply
A3020
Thanks. C571 now picks the right template. The navArray is still persistent, but your navArray = array() works fine.