Jump to:

3393 Posts in 976 Topics by 852 members

Template Questions

SilverStripe Forums » Template Questions » Traverse All Parents of a Page and Exiting A Control Loop

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1
Go to End
Author Topic: 2277 Views
  • craigcordell
    Avatar
    Community Member
    6 Posts

    Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    My apologies if this has already been covered. Spent several hours searching but not finding a solution so...

    Two part question...

    One - Is it possible to upwardly traverse all parents of page in a control block? For example to add all sidebar widgets from each parent...

    <% control Parents %>
       $Sidebar
    <% end_control %>

    Two - Can you exit a control if a condition is met? Example - traverse parents until we find a sidebar then display...

    <% control Parents %>
       $Sidebar
       <% if Sidebar %>
          [[[ exit the control loop ]]]
       <% end_if %>
    <% end_control %>

    Thanks in advance for any help you may have. First project using SS but thoroughly impressed so far.

  • Willr
    Avatar
    Forum Moderator
    5462 Posts

    Re: Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    Hi,

    No this is not possible, Only ways to go back up the tree is to use Parent which is 1, Nested Parents like Parent.Parent or use Top (which is the topmost parent). If you want to traverse back up the tree then you'll need to do that in PHP and while a while loop kinda like

    // mysite/code/Page.php

    function ParentSidebar() {
    $parent = $this->Parent();

    while($parent && $parent->exists()) {

    // do your check

    $parent = $this->Parent();
    }
    }

    Then you can use $ParentSidebar() in the template

  • Willr
    Avatar
    Forum Moderator
    5462 Posts

    Re: Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    Hi,

    No this is not possible, Only ways to go back up the tree is to use Parent which is 1, Nested Parents like Parent.Parent or use Top (which is the topmost parent). If you want to traverse back up the tree then you'll need to do that in PHP and while a while loop kinda like

    // mysite/code/Page.php

    function ParentSidebar() {
    $parent = $this->Parent();

    while($parent && $parent->exists()) {

    // do your check

    $parent = $this->Parent();
    }
    }

    Then you can use $ParentSidebar() in the template

  • craigcordell
    Avatar
    Community Member
    6 Posts

    Re: Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    Thanks for the quick reply. Based on the number of posts that you have, I see you are a busy guy. I appreciate you taking the time to respond.

    The code above does have a typo - $this->Parent() should be $parent->Parent() right? Original will just loop.

    So based on your code I created a new method in my page model like so...

       function Parents( )
       {   
          $parent = $this->Parent();

          $output = new DataObjectSet();
          
          while( $parent && $parent->exists() )
          {
             $output->push( $parent );
             $parent = $parent->Parent();         
          }

          return $output;
       }

    Then in my template file...

                <% if Sidebar.Items %>
                   $Sidebar
                <% else %>
                   <% control Parents %>
                      <% if Sidebar.Items %>
                         $Sidebar
                      <% end_if %>
                   <% end_control %>
                <% end_if %>

    It works great. Now I just need a way to break out of a control block if a condition is met. Any way to do that?

    If not is there a way to extend the template parser without modifying the source? Could see this being useful for lots of other situations.

    Also, is there a way to extend whatever class handles Parents()? Would like to create some generic methods for traversing hierarchical data like Siblings, ParentsUntil, Closest, etc. Use a lot of jQuery so its nice to have a way to move around a selection.

    Thanks again. Look forward to your reply.

  • craigcordell
    Avatar
    Community Member
    6 Posts

    Re: Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    Still have not found a way to break out of a control loop based on a condition so to resolve this issue I placed the following method in Page.php ...

       function FirstParentMatching( $field, $value = NULL )
       {
          $parent = $this->Parent();

          $output = new DataObjectSet();

          while( $parent && $parent->exists() && !$output->items )
          {         
          
             $fieldID = $field . 'ID';
             
             if ( $value == NULL && ( $parent->$field || $parent->$fieldID ) )
             {
                $output->push( $parent );
             }
             else if ( $value != NULL && ( $parent->$field == $value || $parent->$fieldID == $value ) )
             {
                $output->push( $parent );
             }
             
             $parent = $parent->Parent();         
          }
          
          return $output;      
       }

    This will step through the current page and its parents to see if a variable has any value or a specific value. Have not fully tested the specific value but should be fine. I'm using this to step through each page's parents to find the first one with a widget.

    Here is my template code...

                <% if Sidebar.Items %>
                   $Sidebar
                <% else %>
                   <% control FirstParentMatching(Sidebar) %>
                      $Sidebar
                   <% end_control %>
                <% end_if %>

    Note that in this instance we are looking for a parent page with a SiderbarID value. Method will return a DataObjectSet one record.

  • craigcordell
    Avatar
    Community Member
    6 Posts

    Re: Traverse All Parents of a Page and Exiting A Control Loop Link to this post

    Also, in my current project I have pages that are siblings of the homepage. The template code above does not accommodate. I want to use the sidebar widgets for the homepage if the current page (a sibling of home) does not have any specified. So we use ...

                <% if Sidebar.Items %>
                   $Sidebar
                <% else_if Parent %>
                   <% control FirstParentMatching(Sidebar) %>
                      $Sidebar
                   <% end_control %>
                <% else %>
                   <% control Page(Home) %>
                      $Sidebar
                   <% end_control %>
                <% end_if %>

    2277 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.