key = idx($data, 'key'); } public function processRequest() { $request = $this->getRequest(); $panels = $this->buildPanels(); $nav = $this->renderSideNav($panels); $key = $nav->selectFilter($this->key, head($panels)->getPanelKey()); $panel = $panels[$key]; $response = $panel->processRequest($request); if ($response instanceof AphrontResponse) { return $response; } $nav->appendChild($response); return $this->buildApplicationPage( $nav, array( 'title' => $panel->getPanelName(), 'device' => true, )); } private function buildPanels() { $panel_specs = id(new PhutilSymbolLoader()) ->setAncestorClass('PhabricatorSettingsPanel') ->setConcreteOnly(true) ->selectAndLoadSymbols(); $panels = array(); foreach ($panel_specs as $spec) { $class = newv($spec['name'], array()); $panels[] = $class->buildPanels(); } $panels = array_mergev($panels); $panels = mpull($panels, null, 'getPanelKey'); $result = array(); foreach ($panels as $key => $panel) { if (!$panel->isEnabled()) { continue; } if (!empty($result[$key])) { throw new Exception(pht( "Two settings panels share the same panel key ('%s'): %s, %s.", $key, get_class($panel), get_class($result[$key]))); } $result[$key] = $panel; } $result = msort($result, 'getPanelSortKey'); return $result; } private function renderSideNav(array $panels) { $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI('/panel/'))); $group = null; foreach ($panels as $panel) { if ($panel->getPanelGroup() != $group) { $group = $panel->getPanelGroup(); $nav->addLabel($group); } $nav->addFilter($panel->getPanelKey(), $panel->getPanelName()); } return $nav; } public function buildApplicationMenu() { $panels = $this->buildPanels(); return $this->renderSideNav($panels)->getMenu(); } }