Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Customising the CMS /

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

Hiding pages in site tree and adding list of children pages to tab


Go to End


39 Posts   12396 Views

Avatar
RShake

Community Member, 3 Posts

7 March 2010 at 12:53pm

Here's what I'd like to do.
1. Add a new boolean field in the behaviour tab called 'Hide Children from site tree'.
2. Use this setting to determine if a page's children will load/appear in the site tree.
3. If this setting is checked for a page, I'd like a new tab to show up that simply has a list of all of the page's children.

I've got the field set up in my behaviour tab no problem.

I'd like suggestions on how to do #2 & #3.

Ideally I'd be able to implement all of this in a module so it could be added to different sites easily, but I'm not sure if I'll be able to do step #2 without modifying some of the core code (Hierarchy.php or LeftAndMain.php).

For the new tab with the list of children pages, I would just want a basic list, with the page name, title, and create date. I would want this to be links which would simply take me to that page to be edited. It would be really nice if I could also sort the pages in the list from that tab as well.

I know about data object & the dataobjectmanager module. I don't want to use those.

As a practical example. Say I have the Blog module, and have a year's worth of daily blog posts. This makes for a very long tree when expanded. If I can implement my solution there would not be any posts below the blogholder in the site tree (assuming you've selected to hide children from site tree). To access a post for editing if you needed to, you would simply go to the 'Children' tab, find the post in the list, and click on it. This would open the standard edit page interface as normal.

Any suggestions on how I might make this work?

Avatar
RShake

Community Member, 3 Posts

9 March 2010 at 4:02pm

No replies, huh? Does that mean what I'd like to do is not possible, or just plain stupid? :)

Avatar
pter

Community Member, 38 Posts

5 May 2010 at 9:14pm

No, that sounds great to me too. Like the Children tab. I think it has been covered and asked elsewhere - one person has described how to hack the sapphire core to do this. But I agree a module is the best solution.

Avatar
pter

Community Member, 38 Posts

6 May 2010 at 7:48am

Found the hack I was referring to - intended to set a 'max children displayed (zero = no children)' value. Haven't looked closely to see if it might be converted from a core hack.

http://www.dio5.com/limiting-subpages-in-silverstripe-cms/

Avatar
pter

Community Member, 38 Posts

6 May 2010 at 8:12am

And extending my search to include the word subpages came up with the same persons own followup with a proper silverstripe extending classes without hacking the core way to fix it for a page type, so you don't have to maintain it for every page

http://www.dio5.com/limiting-subpages-in-silverstripe/

Yet to try it myself, will let you know.

Avatar
RShake

Community Member, 3 Posts

6 May 2010 at 8:33am

Wow pter--good work on this.

It really looks like you're on the right track here. If I can get this to work to hide pages from the site tree, I'll nearly have what I wanted. I'm thinking it should be relatively easy to show a "Children Tab" and display all of the children of a page.

Hopefully this can be made into a module to be easily added to any site. I'm betting many would find it very useful.

Thanks for your good work.

Avatar
pter

Community Member, 38 Posts

6 May 2010 at 12:51pm

VCool.

Works nicely with a couple of mods. I have implemented a 'first X' and a 'show no children at all' via extension classes LimitedHierarchy & StopHierarchy. Also got my 'children' (or in my case 'Articles') tabpage sorted as (at present) a simple table. Using the StopHierarchy it now shows no subpages for this class (woohoo) but, as you also desired, the class has a tab showing all child pages with 'view' and 'edit' options (no Delete needed as that is on the CMS Edit page and only one extra click). It does not affect my other child/sub page showing as this is done using a direct 'get()' from the database which isn't affected by the modified CMS limiting stageChildren().

Only problem with the 'first X' is the sorting. With the code as it stands it tries to sort on Date - but as this is present in nearly every Page that inherits from SiteTree mysql spits out an error complaining the Date field in the sort clause is ambiguous. Without it you are limited to the natural sort order which may not be as desired (e.g. if you wanted to show the most recent X in the CMS).

Will post code in a moment but must do some lunchtime things.

Avatar
pter

Community Member, 38 Posts

6 May 2010 at 4:27pm

Edited: 06/05/2010 8:13pm

Righty ho. Yes this would make a nice module and I'm sure it can be done and will have a go myself. However as I'm just getting into Silverstripe it will take a bit to sort out the injecting of methods, extra editor fields and tabs, peeking at how other modules do it, and so on that would need to be done to extend the SiteTree class nicely.

However it is all fine just using the code from the guy at the dio5 site, I did little more than wrap it for my own amusement. Other than the sort by Date issue - which is kinda crucial to getting the X Most Recent.

What follows is the extras added to my ArticleHolder to hide the ArticlePages it holds 'below'. Crude but works and I'm sure one of us will do a better job in time. Including dbfields in the owner object to have a nice CMS specifiable limit and your checkbox (so you can have a limit of zero mean show zero [=none] as opposed to disabled).

Inside the ArticleHolder.php class file in mysite/code directory

<?php
class ArticleHolder extends Page {

   [... other stuff like $db and so on ...]

   static $extensions = array('StopHierarchy'); // or could be LimitHierarchy

   function getCMSFields() {
     $fields = parent::getCMSFields();

     // get the children to add to article list with View & Edit options (as Delete is in the Edit)

     $children = DataObject::get("ArticlePage", "ParentID = $this->ID", "Date DESC");
     if( !$children ) $childList = 'No articles found'; // no children, nothing to work with
     else {
       $childList = '<table width=100% border=0 cellpadding=0 cellspacing=0 background-color=#efefef>';
       $bgcolor = '#ffe';
       foreach ($children as $achild) {
         $childList .= '<tr>';
         $childList .= '<td style="border: 1px solid #ddd; background-color: '.$bgcolor.'; padding: 0.5em 1em 0.5em 1em; margin: 0; width: 4em; text-align: center;"><a href="'.$achild->URLSegment.'">View</a></td>';
         $childList .= '<td style="border: 1px solid #ddd; background-color: '.$bgcolor.'; padding: 0.5em 1em 0.5em 1em; margin: 0; width: 4em; text-align: center;"><a href="admin/show/'.$achild->ID.'">Edit</a></td>';
         $childList .= '<td style="border: 1px solid #ddd; background-color: '.$bgcolor.'; padding: 0.5em 1em 0.5em 1em; margin: 0;  text-align: left;">'.$achild->Date.' to '.$achild->EndDate.': '.$achild->Title.'</td>';
         $childList .= '</tr>';
         $bgcolor = ($bgcolor == '#ffe')?'#eff':'#ffe';
       }
       $childList .= '</table>';
     }

     $fields->addFieldToTab('Root.Content.Articles', new LiteralField('Articles',$childList));
     return $fields;
   }

}

[.. possibly more stuff here too (O: ...]

?>

The LimitHierarchy.php, also in mysite/code at the moment.

<?php

class LimitHierarchy extends Hierarchy {
    
    public function stageChildren($showAll = false) 
    {
        $baseClass = ClassInfo::baseDataClass($this->owner->class);
        $extraFilter = $showAll ? '' : " AND ShowInMenus = 1";
        $filter = "`{$baseClass}`.`ParentID` = " . (int)$this->owner->ID;
        $filter .= " AND `{$baseClass}`.ID != " . (int)$this->owner->ID;
        $filter .= $extraFilter;
        
        if(Director::urlParam("Action") == "getfilteredsubtree" 
        && (!empty($_REQUEST['SiteTreeSearchTerm']) || !empty($_REQUEST['SiteTreeFilterDate'])))
        {            
//            ** it no like the Date sort - ambiguous as is in all, need to find the right way to specify it just for one **
//            $staged = DataObject::get($baseClass, $filter, "Date ASC");
            $staged = DataObject::get($baseClass, $filter, "");
            if(!$staged) $staged = new DataObjectSet();
            $this->owner->extend("augmentStageChildren", $staged, $showAll);
            return $staged;
        }
        
        else
        {
            // tiny limit so it is obvious it had an effect
            $limit = 2;
//origcode            $set = DataObject::get($baseClass, $filter, "Date DESC", "", $limit);
//origcode            $set->sort("Date","ASC");

//            ** it no like the Date sort - ambiguous as is in all, need to find the right way to specify it just for one **
//            $set = DataObject::get($baseClass, $filter, "`SiteTree`.Date DESC", "", $limit);
            $set = DataObject::get($baseClass, $filter, "", "", $limit);
            return $set;    
        }
    }

}

?>

The StopHierarchy.php, also in mysite/code at the moment. Note is the same as the LimitHierarchy class but just returns false on the stageChildren equivalent to stop CMS crawl in its tracks. Also quicker (O:

<?php

class StopHierarchy extends Hierarchy {

    // unless we have special reason to hunt then (as per lower return null) stop showing children in the CMS hierarchy here
    
    public function stageChildren($showAll = false) 
    {
        $baseClass = ClassInfo::baseDataClass($this->owner->class);
        $extraFilter = $showAll ? '' : " AND ShowInMenus = 1";
        $filter = "`{$baseClass}`.`ParentID` = " . (int)$this->owner->ID;
        $filter .= " AND `{$baseClass}`.ID != " . (int)$this->owner->ID;
        $filter .= $extraFilter;
        
        if(Director::urlParam("Action") == "getfilteredsubtree" 
        && (!empty($_REQUEST['SiteTreeSearchTerm']) || !empty($_REQUEST['SiteTreeFilterDate'])))
        {            
//            $staged = DataObject::get($baseClass, $filter, "Date ASC");
            $staged = DataObject::get($baseClass, $filter, "");
            if(!$staged) $staged = new DataObjectSet();
            $this->owner->extend("augmentStageChildren", $staged, $showAll);
            return $staged;
        }
        
        else return new DataObjectSet(); // just Stop
    }

}

?>

Go to Top