Programmically creating autonav and using a 'custom' displayPages

Permalink 1 user found helpful
Thanks to the great threads at http://www.concrete5.org/community/forums/themes/perist-autonav-tem... and http://www.concrete5.org/index.php?cID=11798... I have been able to create an autonav block in a page type defaults page. I got that up and running great, but I want to expand on it a bit and display navigation for pages under a specific page with the handle 'top-navigation' instead of pulling from the root of the sitemap. However, I only want to display the navigation for that page if the Collection exists. If it doesn't I want it to pull from the root of the sitemap. The code I have is:

<?php
  $autoNavBlock = BlockType::getByHandle('autonav');
  $navPageRoot = Collection::getByHandle('top-navigation');
  if(is_object($navPageRoot))
  { /* Top Navigation Found */
     $autoNavBlock->controller->displayPages = 'custom';
     $autoNavBlock->controller->displayPagesCID = $navPageRoot->getCollectionID();
  }
  else
  { /* Use root for default */
     $autoNavBlock->controller->displayPages = 'top';
  }
  $autoNavBlock->controller->orderBy = 'display_asc';
  $autoNavBlock->controller->displaySubPages = 'all';
  $autoNavBlock->controller->displaySubPageLevels = 'all';


Just in case the page that I want to pull the navigation from gets deleted or moved around I want to get the id of it by using the handle instead of putting a static value in there. However, I noticed Collection::getByHandle()'s code creates the Collection if it doesn't exist, so if the 'top-navigation' page doesn't exist it will display a blank navigation instead of the default. I did notice in the comments for that function it states "This function is slightly misnamed: it should be getOrCreateByHandle($handle)..." so I know it is acting as expected. Would the way to do this be to copy the Collection controller over and add a function like getByHandleNoCreate(), or is there some other function I should be using for this purpose?

Thanks!

- Donald

 
jordanlev replied on at Permalink Reply
jordanlev
Instead of checking:
if (is_object($navPageRoot))


check:
if ($navPageRoot->getCollectionID() > 0)


I think what those comments in the getByHandle() code mean is that an OBJECT is created, not the page itself -- but this object that's created is just an empty shell of a hypothetical page that could exist some day (maybe) -- if you check its cID, it should be 0 for these non-existent pages.
dukman821 replied on at Permalink Reply
Hey Jordanley,

Thanks for replying. I appreciate it!

I checked out the return value of getCollectionID() and it returns a value > 0 if the collection exists and isn't a page, or doesn't exist but is then created. When the call is made again with the same handle the same ID is returned. I change the handle (to one that doesn't exist) and then get another ID > 0. It looks like it does add it to the database. However, if I do request a handle that does exist but it is a page, then it doesn't return an object and thus the is_object() check must be made before using it.

I'll do some more poking around.

Thanks!

- Donald
dukman821 replied on at Permalink Reply
Since the Collection model only returns basic collections (with no pages) and autonav is looking for a Page anyways, I thought that maybe there would be a method in the Page model. However, I looked there and only see getByID(), but nothing about doing a getByHandle(). I am still new to the api so be gentle if it's there's another obvious way.
jordanlev replied on at Permalink Reply
jordanlev
This part of the API isn't documented, so don't feel bad :)

I think you're on the right track with using Page instead of Collection. There is a Page::getByPath method, and I have used it in code and it works -- but it takes a path to a page, not a handle, which means you need to precede the handle with a slash. For example:
$navPageRoot = Page::getByPath('/top-navigation');
if ($navPageRoot->cID) {
  /* top navigation found... */
} else {
  /* use root for default... */
}


$navPageRoot->cID is NULL if no page exists, or a non-zero number if the page does exist.

Of course, this only checks for the page at one location in your site -- if the page exists but is a sub-page of another page, you'd need to check for it there explicitly ( e.g. Page::getByPath('/some-page/top-navigation'); ).

Hope this works for your situation.

-Jordan
dukman821 replied on at Permalink Reply
Using Page::getByPath() works out fine for my situation. Basically what I am doing is giving the person that's going to be editing the site a single location he edits items, and their order, that show up in the top navigation. I forgot though that I would get urls likehttp://www.site.com/index.php/top_navigation/page_below_top_navigat... when using this method, but it is as expected. I might go back to pulling from the root to avoid the extra addition to the path, but it's nice to have another method available.

Thanks for the help Jordan!

- Donald