PageList filterBy Grandparent ID

Permalink
Hi guys, I'm trying to do a filter on a pagelist by a grandparent id number.

I can get this working by getting all of the pages of a certain type, and then in my template I work out what it's grandparent id is and if it matches one that is sent to the controller of pagelist. But it's not very elegant. I'm just wondering if anyone has managed to create a method for pagelist so you can do $pl->filterByGrandparentID(value here) or something similar?

Thanks, Adam.

adz
 
adz replied on at Permalink Best Answer Reply
adz
I have managed to solve this.

in the models/page_list.php file add:
/** 
    * Sets the parent ID's that we will grab pages from. 
    * @param mixed $cParentIDs
    */
   public function filterByParentIDs($cParentIDs) {
      $this->filterByCParentID = $cParentID;
                $this->filter(false, '(p1.cParentID IN' . $cParentIDs . ')');
   }


This is our new filter function.

In the pagelist controller add:

if ( intval($this->grandparentID) != 0) {
            $new_pl = new PageList();
            $new_pl->filterByParentID($this->grandparentID);
            $new_pages = $new_pl->getPage();
            $cParentIDs = "(";
            foreach($new_pages as $new_page) {
               $cParentIDs .= $new_page->cID . ",";
            }
            $cParentIDs = substr($cParentIDs, 0, -1);
            $cParentIDs .= ")";
            $pl->filterByParentIDs($cParentIDs);
         }


This will generate a second PageList within the one you are trying to get, and then populate a variable with a list of all the children ID's, this you will then add as a filter to the normal pagelist you are generating.
beebs93 replied on at Permalink Reply
beebs93
Out of curiosity, could you not use the $pl->filterByPath() method to target a parent page then have it return all pages under that path?
adz replied on at Permalink Reply
adz
I did it this way as I needed a PageList because I was also filtering by other elements, one being the ctID
beebs93 replied on at Permalink Reply
beebs93
Sorry, I didn't catch you wanted only two levels deep.

You could probably skip the first page list by (whether it's any faster I'm not sure - but it keeps from making new copies of core models):

$arrParentIDs = array();
$objGrandParent = Page::getByID($this->grandParentID);
$arrParentIDs = $objGrandParent->getCollectionChildrenArray($oneLevelOnly = TRUE);
$strFilter = '(p1.cParentID IN(' . implode(',', $arrParentIDs) . '))';


Then, you can do your normal $pl->filter(false, $strFilter);

In your example, if you wanted to add any additional filters/sorts to the initial array of parent pages then this method obviously wouldn't work as "getCollectionChildrenArray" doesn't take that into account.

You could, theoretically, iterate through said array ($arrParentIDs), get each Page object, check for whatever attribute, blah blah, but at that point a simple page list as in your example is the more efficient route.
adz replied on at Permalink Reply
adz
I thought about using "getCollectionChildrenArray" but I needed to filter it on a couple of different attributes, thus why I thought that dropping it into the controller for a PageList would have been better.

But thanks anyway beebs93 !