/** * Accepts array('info' => [page info array], all options accepted by getPagesInfo except where) * @param mixed $options * @return mixed */ public static function getParentInfo($options) { $info = aPageTable::getAncestorsInfo($options); if (count($info)) { return $info[count($info) - 1]; } return false; }
/** * 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']; }