diff --git a/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php b/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php index 3c86d19a58..87b59e3e0f 100644 --- a/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php +++ b/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php @@ -7,7 +7,7 @@ final class PhabricatorFavoritesProfileMenuEngine return true; } - protected function getItemURI($path) { + public function getItemURI($path) { $object = $this->getProfileObject(); $custom = $this->getCustomPHID(); diff --git a/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php b/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php index ebcc92b189..528edba697 100644 --- a/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php +++ b/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php @@ -7,7 +7,7 @@ final class PhabricatorHomeProfileMenuEngine return true; } - protected function getItemURI($path) { + public function getItemURI($path) { $object = $this->getProfileObject(); $custom = $this->getCustomPHID(); diff --git a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php index 9965147a12..3d67872772 100644 --- a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php +++ b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php @@ -10,7 +10,7 @@ final class PhabricatorPeopleProfileMenuEngine return false; } - protected function getItemURI($path) { + public function getItemURI($path) { $user = $this->getProfileObject(); $username = $user->getUsername(); $username = phutil_escape_uri($username); diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php index d2f8d4f58d..7d5dc37e0b 100644 --- a/src/applications/project/controller/PhabricatorProjectViewController.php +++ b/src/applications/project/controller/PhabricatorProjectViewController.php @@ -25,9 +25,10 @@ final class PhabricatorProjectViewController $controller_object = new PhabricatorProjectBoardViewController(); break; case PhabricatorProject::ITEM_PROFILE: - default: $controller_object = new PhabricatorProjectProfileController(); break; + default: + return $engine->buildResponse(); } return $this->delegateToController($controller_object); diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php index d3ea39e1e2..a39e7a8236 100644 --- a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php @@ -7,7 +7,7 @@ final class PhabricatorProjectProfileMenuEngine return true; } - protected function getItemURI($path) { + public function getItemURI($path) { $project = $this->getProfileObject(); $id = $project->getID(); return "/project/{$id}/item/{$path}"; diff --git a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php index 1bd7e796dc..ddb59ec095 100644 --- a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php @@ -18,11 +18,6 @@ final class PhabricatorProjectManageProfileMenuItem return false; } - public function canMakeDefault( - PhabricatorProfileMenuItemConfiguration $config) { - return true; - } - public function getDisplayName( PhabricatorProfileMenuItemConfiguration $config) { $name = $config->getMenuItemProperty('name'); diff --git a/src/applications/search/engine/PhabricatorProfileMenuEngine.php b/src/applications/search/engine/PhabricatorProfileMenuEngine.php index 3e11436ced..a6db1b2d2b 100644 --- a/src/applications/search/engine/PhabricatorProfileMenuEngine.php +++ b/src/applications/search/engine/PhabricatorProfileMenuEngine.php @@ -82,7 +82,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { return $this->showNavigation; } - abstract protected function getItemURI($path); + abstract public function getItemURI($path); abstract protected function isMenuEngineConfigurable(); abstract protected function getBuiltinProfileItems($object); @@ -102,6 +102,9 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { $request = $controller->getRequest(); $item_action = $request->getURIData('itemAction'); + if (!$item_action) { + $item_action = 'view'; + } // If the engine is not configurable, don't respond to any of the editing // or configuration routes. @@ -136,6 +139,12 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { } } + if (!$selected_item) { + if ($item_action == 'view') { + $selected_item = $this->getDefaultItem(); + } + } + switch ($item_action) { case 'view': case 'info': @@ -159,21 +168,33 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { } $navigation = $this->buildNavigation(); - $navigation->selectFilter('item.configure'); $crumbs = $controller->buildApplicationCrumbsForEditEngine(); - switch ($this->getMenuType()) { - case 'personal': - $crumbs->addTextCrumb(pht('Personal')); - break; - case 'global': - $crumbs->addTextCrumb(pht('Global')); - break; + + // TODO: This stuff might need a little tweaking at some point, since it + // causes "Global" and "Personal" to show up in contexts where they don't + // make sense, notably Projects. + if ($item_action != 'view') { + $navigation->selectFilter('item.configure'); + switch ($this->getMenuType()) { + case 'personal': + $crumbs->addTextCrumb(pht('Personal')); + break; + case 'global': + $crumbs->addTextCrumb(pht('Global')); + break; + } } switch ($item_action) { case 'view': + $navigation->selectFilter($selected_item->getItemIdentifier()); + $content = $this->buildItemViewContent($selected_item); + $crumbs->addTextCrumb($selected_item->getDisplayName()); + if (!$content) { + return new Aphront404Response(); + } break; case 'configure': $content = $this->buildItemConfigureContent($item_list); @@ -225,6 +246,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { if ($this->getShowNavigation()) { $page->setNavigation($navigation); } + return $page; } @@ -269,13 +291,8 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { if (count($items) == 1) { $item = head($items); if ($item->getKey() === null) { - $builtin_key = $menu_item->getBuiltinKey(); - $item_phid = $menu_item->getPHID(); - if ($builtin_key !== null) { - $item->setKey($builtin_key); - } else if ($item_phid !== null) { - $item->setKey($item_phid); - } + $item_identifier = $menu_item->getItemIdentifier(); + $item->setKey($item_identifier); } } @@ -326,6 +343,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { foreach ($stored_items as $stored_item) { $impl = $stored_item->getMenuItem(); $impl->setViewer($viewer); + $impl->setEngine($this); } // Merge the stored items into the builtin items. If a builtin item has @@ -442,6 +460,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { $item = clone $item; $item->setViewer($viewer); + $item->setEngine($this); $builtin ->setProfilePHID($object->getPHID()) @@ -546,6 +565,10 @@ abstract class PhabricatorProfileMenuEngine extends Phobject { ->setURI($this->getConfigureURI()); } + private function buildItemViewContent( + PhabricatorProfileMenuItemConfiguration $item) { + return $item->newPageContent(); + } private function buildItemConfigureContent(array $items) { $viewer = $this->getViewer(); diff --git a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php index c9a13bd4ab..002e5778d5 100644 --- a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php +++ b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php @@ -21,6 +21,11 @@ final class PhabricatorDashboardProfileMenuItem return true; } + public function canMakeDefault( + PhabricatorProfileMenuItemConfiguration $config) { + return true; + } + public function attachDashboard($dashboard) { $this->dashboard = $dashboard; return $this; @@ -28,14 +33,39 @@ final class PhabricatorDashboardProfileMenuItem public function getDashboard() { $dashboard = $this->dashboard; + if (!$dashboard) { return null; } else if ($dashboard->isArchived()) { return null; } + return $dashboard; } + public function newPageContent( + PhabricatorProfileMenuItemConfiguration $config) { + $viewer = $this->getViewer(); + + $dashboard_phid = $config->getMenuItemProperty('dashboardPHID'); + + // Reload the dashboard to attach panels, which we need for rendering. + $dashboard = id(new PhabricatorDashboardQuery()) + ->setViewer($viewer) + ->withPHIDs(array($dashboard_phid)) + ->needPanels(true) + ->executeOne(); + if (!$dashboard) { + return null; + } + + $engine = id(new PhabricatorDashboardRenderingEngine()) + ->setViewer($viewer) + ->setDashboard($dashboard); + + return $engine->renderDashboard(); + } + public function willBuildNavigationItems(array $items) { $viewer = $this->getViewer(); $dashboard_phids = array(); @@ -100,7 +130,7 @@ final class PhabricatorDashboardProfileMenuItem $icon = $dashboard->getIcon(); $name = $this->getDisplayName($config); - $href = $dashboard->getViewURI(); + $href = $this->getItemViewURI($config); $item = $this->newItem() ->setHref($href) diff --git a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php index 6f1342d4c0..061afc7fad 100644 --- a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php +++ b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php @@ -3,6 +3,7 @@ abstract class PhabricatorProfileMenuItem extends Phobject { private $viewer; + private $engine; final public function buildNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { @@ -55,6 +56,15 @@ abstract class PhabricatorProfileMenuItem extends Phobject { return $this->viewer; } + public function setEngine(PhabricatorProfileMenuEngine $engine) { + $this->engine = $engine; + return $this; + } + + public function getEngine() { + return $this->engine; + } + final public function getMenuItemKey() { return $this->getPhobjectClassConstant('MENUITEMKEY'); } @@ -70,6 +80,20 @@ abstract class PhabricatorProfileMenuItem extends Phobject { return new PHUIListItemView(); } + public function newPageContent( + PhabricatorProfileMenuItemConfiguration $config) { + return null; + } + + public function getItemViewURI( + PhabricatorProfileMenuItemConfiguration $config) { + + $engine = $this->getEngine(); + $key = $config->getItemIdentifier(); + + return $engine->getItemURI("view/{$key}/"); + } + public function validateTransactions( PhabricatorProfileMenuItemConfiguration $config, $field_key, diff --git a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php index 107fa63c72..f178cc49fe 100644 --- a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php +++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php @@ -185,6 +185,19 @@ final class PhabricatorProfileMenuItemConfiguration return ($this->getVisibility() === self::VISIBILITY_DEFAULT); } + public function getItemIdentifier() { + $id = $this->getID(); + + if ($id) { + return (int)$id; + } + + return $this->getBuiltinKey(); + } + + public function newPageContent() { + return $this->getMenuItem()->newPageContent($this); + } /* -( PhabricatorPolicyInterface )----------------------------------------- */