Esempio n. 1
0
 /**
  * Accordion nav
  * Always starts with the children of the root and comes down to the level of this page's children,
  * listing peers of this page's ancestors at every level. That is:
  * Home
  * One
  * 1a
  * 1b
  * 1bx  <-- the current page
  * 1bxA
  * ibxB
  * 1c
  * Two
  * You can now specify the root slug, which defaults to the home page.
  * Note that children of Two, 1a, and 1c are NOT returned. Only the siblings of
  * the current page's ancestors, the current page and its siblings, and the immediate
  * children of the current page are returned. For a full tree use getTreeInfo().
  * The livingOnly flag is present for bc only and is ignored, we get what the current user can see
  * @param mixed $livingOnly
  * @param mixed $depth
  * @param mixed $root
  * @return mixed
  */
 public function getAccordionInfo($livingOnly = true, $depth = null, $root = '/')
 {
     // As far as I can tell there is no super-elegant, single-query way to do this
     // without fetching a lot of extra pages. So do a peer fetch at each level.
     // First build an array of arrays listing the peers at each level
     // If you have enabled children of archived ancestors and you don't
     // want the ancestors to show up, you probably shouldn't be using
     // an accordion contro. in the first place
     // We need all of the ancestors to build an accordion successfully, in particular
     // since we often want a hidden parent to be the root. Give more thought to whether
     // we can do this just for the root
     $ancestors = aPageTable::getAncestorsInfo(array('info' => $this->getInfo(), 'ignore_permissions' => true));
     // Dump ancestors we don't care about
     $found = false;
     for ($i = 0; $i < count($ancestors); $i++) {
         if ($ancestors[$i]['slug'] === $root) {
             $rootLevel = $ancestors[$i]['level'];
             $ancestors = array_slice($ancestors, $i);
             $found = true;
             break;
         }
     }
     if (!$found) {
         // Active page is not a descendant of the root. Just return the children of the root.
         // This makes the accordion more useful when you are not yet under its root
         // I don't have a handy way to do this without cache issues in the table class yet so...
         // This is not a proper info structure but it will work for this job
         $rootInfo = Doctrine::getTable('aPage')->createQuery('p')->where('slug = ?', array($root))->execute(array(), Doctrine::HYDRATE_ARRAY);
         if (!count($rootInfo)) {
             throw new sfException("Root page of accordion does not exist!");
         }
         $rootInfo = $rootInfo[0];
         return aPageTable::getChildrenInfo(array('info' => $rootInfo));
     }
     $result = array();
     foreach ($ancestors as $ancestor) {
         if ($ancestor['level'] > $rootLevel && $livingOnly && $ancestor['archived']) {
             continue;
         }
         $lineage[] = $ancestor['id'];
         if ($ancestor['level'] == $rootLevel) {
             $result[] = array($ancestor);
         } else {
             // TODO: this is inefficient, come up with a way to call getPeerInfo for an
             // alternate ID without fetching that entire page
             $peers = aPageTable::retrieveBySlug($ancestor['slug'])->getPeerInfo($livingOnly);
             $result[] = $peers;
         }
     }
     // Current page peers level
     $result[] = $this->getPeerInfo($livingOnly);
     $lineage[] = $this->id;
     // Current page children level
     $result[] = $this->getChildrenInfo($livingOnly);
     // Now fix it up to be a properly nested array like that
     // returned by getTreeInfo(). On each pass take a reference
     // to the child that will own the children of the next pass
     $accordion = $result[0][0];
     $current =& $accordion;
     for ($i = 0; $i < count($result) - 1; $i++) {
         $current['children'] = $result[$i + 1];
         if ($i + 1 < count($lineage)) {
             // We've already started returning the kids as a flat array so
             // we need to scan for it unfortunately. This entire method could
             // use more attention to performance
             foreach ($current['children'] as &$child) {
                 if ($child['id'] == $lineage[$i + 1]) {
                     $current =& $child;
                     break;
                 }
             }
         }
     }
     // Don't return the home page itself, start with the tabs.
     // This is consistent with getTreeInfo() which should simplify implementations.
     // It's easy to add the home page in at a higher level if desired.
     return $accordion['children'];
 }