How do I make a parent page automatically go to a sub page

Permalink 1 user found helpful
Hi, I'm new to concrete 5 and I'm trying to figure out how to make a parent page automatically redirect to a sub page.

For example: In the following set up I would like 'Primary Page Two' to automatically go to 'Sub Page One'

-Primary Page One
-Primary Page Two
--Sub Page One
--Sub Page Two
-Primary Page Three

I assumed that this was the default behavior when I first started using the site map since it displayed parent pages as folders rather than pages. However this is not the case (a small UI issue in my view).

After some searching around I found out that I can assign a 'page attribute' to the particular parent page that I want to skip and go directly to the first sub page of that parent page. The page attribute that does this is 'replace_link_with_first_in_nav'. However I haven't got a clue where I am supposed to assign this attribute?

I have gone to the parent page I want to skip, selected 'Page Properties', then 'Custom Attributes' however it does not give me the option to 'replace_link_with_first_in_nav'.

View Replies: View Best Answer
mikenz replied on at Permalink Reply
So I think I've got it figured it out. (sort of)

In order to enable this custom attribute you first have to go to: Dashboard > Pages and Themes > Attributes and then add it as a page attribute.

The Attribute Type = Checkbox
The Handle = replace_link_with_first_in_nav
The Name = Replace link with first subpage in nav (or whatever you want to call it)

Now it will show up as an option to select under 'Page Properties', then 'Custom Attributes'

So now when I click on the page from the main menu it takes me to the sub page however the original page is still there if I navigate to it manually.

Surely there must be a better way than this?
cherrycake replied on at Permalink Reply
cherrycake
Unfortunately not. There's no native redirect option in Concrete5 as of yet. The attribute was made specifically for the navbar, thus only the page link get's replaced with the first child if the attribute is set. It's not really a redirect at all.

The only way to add a redirect to any page is to either do a lazy one by adding some javascript to that page that will redirect upon loading, or to mess around with custom page types or custom attributes.

There are a few examples of this around the forum. The ideal way to do it imo would be to add support for it in the C5 core by checking for some page property before rendering and redirecting from there.
Sergio replied on at Permalink Reply
Sergio
I managed to get that by using the attribute above and get the nav link replaced as said AND by using this code below on my header.php.

global $c;
   if($c->getCollectionAttributeValue('replace_link_with_first_in_nav')) {
      $nh = Loader::helper('navigation');
      $subPage = $c->getFirstChild();
      if ($subPage instanceof Page) {
         $pageLink = $nh->getLinkToCollection($subPage);
         header("Location: $pageLink");
         exit;
      }
   };
Ale replied on at Permalink Reply
Sergio: Thanks for your solution, it looks somewhat the same that I have been using.

I wonder if anyone has come up with a solution that works with the full page cache on 5.4.1? Redirect commands in the header.php won't run if the page is cached as static html...only way I got around this was to disable cache for spesific pages.

I hoping to see a ready-made solution in Concrete core in upcoming releases..
KingBerT replied on at Permalink Reply
KingBerT
Hello,
I've implemented the Redirection via Events described here:http://www.concrete5.ch/board/?topicID=21...
This site is in German - if you do not understand it, you can contact me.
Maybe this solution works with the full page cache - don't know how to prove that.
so long
Ale replied on at Permalink Best Answer Reply
(please note the edits below)
Thanks KingBerT,

For some reason I'm getting following error:

Non-static method RedirectUrl::redirectUrl() cannot be called statically in ***/events.php on line 164

EDIT!! The following code should work:
config/site.php
define('ENABLE_APPLICATION_EVENTS', true);


config/site_events.php
Events::extend('on_page_view','RedirectUrl','process','helpers/redirect_url.php');


helpers/redirect_url.php
class RedirectUrl {
    function process($page) { 
         if(!isset($_SESSION['uID'])){
            $nh = Loader::helper('navigation');
            if ($c->getCollectionAttributeValue('redirect_to_first_child')) {
                $subPage = $c->getFirstChild();
                if ($subPage instanceof Page) {
                    $pageLink = $nh->getLinkToCollection($subPage);
                }
                header("location: ".BASE_URL.$pageLink);
            }
        }
    }
}
KingBerT replied on at Permalink Reply
KingBerT
Hehe,
there is an error in the german site.
You have to rename the method
"function redirectUrl($page)" to
"public static function process($page)".

1. it must be static,
2. it cannot have the same name as the class (it would be interpreted as constructur).

Don't forget to edit the method name (rename 'redirectUrl' to 'process') in the Events::extend method in site_events.php
Ale replied on at Permalink Reply
Thanks, got it working now.

However, the event "on_before_render" does not fire if the page is cached. Using "on_page_view" seems to work even with cache.
Ale replied on at Permalink Reply
Note: I also edited my message above and it should now have working code.
clickactivate1 replied on at Permalink Reply
I'm really new to the Concrete 5 CMS and I'm not sure if I have this wrong, but I'm hoping this might help and make things easier without having to break into the code: ,
I was playing around with my site and I discovered if you go to the : Dashboard > Sitemap > ( you can change the parent/ child relationship pretty easily )
Once you are in the Sitemap,
I believe that you'll see all the pages in your website -
Select the page you wish to make into a subpage (child) .
grab it and just move it up or down the list and drop it on top of the page you wish to be the parent.
A dialog box will pop up and ask you what you want to do - it gives a few options.
I hope this helps.

KT
jegra replied on at Permalink Reply
Quick note... I had to declare $c as global in the process() function. Otherwise, worked perfectly - thanks!
admin replied on at Permalink Reply
As said jegra later need to put c as global in the class otherwise got a fatal error :
Fatal error: Call to a member function getCollectionAttributeValue() on a non-object

So complete code in helpers/redirect_url.php :
class RedirectUrl {
    function process($page) {
         global $c;
         if(!isset($_SESSION['uID'])){
            $nh = Loader::helper('navigation');
            if ($c->getCollectionAttributeValue('redirect_to_first_child')) {
                $subPage = $c->getFirstChild();
                if ($subPage instanceof Page) {
                    $pageLink = $nh->getLinkToCollection($subPage);
                }
                header("location: ".BASE_URL.$pageLink);
            }
        }
    }
}
TheRealSean replied on at Permalink Reply
TheRealSean
not sure if this is still the best way to do this?
but instead of the Global use the following fuction.
class RedirectUrl {
    function process($page) {
         $c = Page::getCurrentPage();
         if(!isset($_SESSION['uID'])){
            $nh = Loader::helper('navigation');
            if ($c->getCollectionAttributeValue('redirect_to_first_child')) {
                $subPage = $c->getFirstChild();
                if ($subPage instanceof Page) {
                    $pageLink = $nh->getLinkToCollection($subPage);
                }
                header("location: ".BASE_URL.$pageLink);
            }
        }
    }
}
TheRealSean replied on at Permalink Reply
TheRealSean
I'm curious to know if this is still valid in 5.7 or with the new coding guidelines and namespaces this should be refactored?

I'm sure the answers here would work but would like to know if anyone can suggest a 5.7 approach to this?

**Edit: I have just seen this is the approach taken in the new autonav so I guess this is still valid :)
foster replied on at Permalink Reply 1 Attachment
foster
Thanks for this post - it was exactly what I was looking for!

One note - not sure why, but in my version of Concrete5 (which is 5.5.1), I have the word "Boolean" instead of "Checkbox". I've seen other installations of 5.5.1 with "Checkbox" in the third slot - but everything worked out perfectly for me by selecting Boolean.

Hope this is helpful to someone out there.

I've attached a screenshot if anyone is curious what the menu looks like with "Boolean".

-Foster