From 08de131da525efbbeb1ca0778c24f263497871f0 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 1 Jan 2016 04:26:36 -0800 Subject: [PATCH] Begin modularizing main menu items Summary: Ref T10077. Ref T8918. The way the main menu is built is not very modular and fairly hacky. It assumes menus are provided by applications, but this isn't exactly true. Notably, the "Quick Create" menu is not per-application. The current method of building this menu is very inefficient (see T10077). Particularly, we have to build it //twice// because we need to build it once to render the item and then again to render the dropdown options. Start cleaning this up. This diff doesn't actually have any behavioral changes, since I can't swap the menu over until we get rid of all the other items and I haven't extended this to Notifications/Conpherence yet so it doesn't actually fix T8918. Test Plan: Viewed menus while logged in, logged out, in different applications, in desktop/mobile. Nothing appeared different. Reviewers: chad Reviewed By: chad Maniphest Tasks: T8918, T10077 Differential Revision: https://secure.phabricator.com/D14922 --- src/__phutil_library_map__.php | 12 +++ .../PhabricatorAuthApplication.php | 42 --------- .../PhabricatorAuthMainMenuBarExtension.php | 73 +++++++++++++++ .../PhabricatorHelpApplication.php | 80 ----------------- .../PhabricatorHelpMainMenuBarExtension.php | 70 +++++++++++++++ .../PhabricatorPeopleApplication.php | 42 --------- .../PhabricatorPeopleMainMenuBarExtension.php | 49 ++++++++++ .../PhabricatorSettingsApplication.php | 22 ----- ...habricatorSettingsMainMenuBarExtension.php | 29 ++++++ .../menu/PhabricatorMainMenuBarExtension.php | 88 ++++++++++++++++++ .../page/menu/PhabricatorMainMenuView.php | 89 ++++++++++++++----- src/view/phui/PHUIMainMenuView.php | 31 +++++++ 12 files changed, 418 insertions(+), 209 deletions(-) create mode 100644 src/applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php create mode 100644 src/applications/help/extension/PhabricatorHelpMainMenuBarExtension.php create mode 100644 src/applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php create mode 100644 src/applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php create mode 100644 src/view/page/menu/PhabricatorMainMenuBarExtension.php create mode 100644 src/view/phui/PHUIMainMenuView.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index fdbd1d7539..22f7832780 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1500,6 +1500,7 @@ phutil_register_library_map(array( 'PHUIListItemView' => 'view/phui/PHUIListItemView.php', 'PHUIListView' => 'view/phui/PHUIListView.php', 'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.php', + 'PHUIMainMenuView' => 'view/phui/PHUIMainMenuView.php', 'PHUIObjectBoxView' => 'view/phui/PHUIObjectBoxView.php', 'PHUIObjectItemListExample' => 'applications/uiexample/examples/PHUIObjectItemListExample.php', 'PHUIObjectItemListView' => 'view/phui/PHUIObjectItemListView.php', @@ -1722,6 +1723,7 @@ phutil_register_library_map(array( 'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php', 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php', + 'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php', 'PhabricatorAuthManagementCachePKCS8Workflow' => 'applications/auth/management/PhabricatorAuthManagementCachePKCS8Workflow.php', 'PhabricatorAuthManagementLDAPWorkflow' => 'applications/auth/management/PhabricatorAuthManagementLDAPWorkflow.php', 'PhabricatorAuthManagementListFactorsWorkflow' => 'applications/auth/management/PhabricatorAuthManagementListFactorsWorkflow.php', @@ -2363,6 +2365,7 @@ phutil_register_library_map(array( 'PhabricatorHelpDocumentationController' => 'applications/help/controller/PhabricatorHelpDocumentationController.php', 'PhabricatorHelpEditorProtocolController' => 'applications/help/controller/PhabricatorHelpEditorProtocolController.php', 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', + 'PhabricatorHelpMainMenuBarExtension' => 'applications/help/extension/PhabricatorHelpMainMenuBarExtension.php', 'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php', 'PhabricatorHighSecurityRequestExceptionHandler' => 'aphront/handler/PhabricatorHighSecurityRequestExceptionHandler.php', 'PhabricatorHomeApplication' => 'applications/home/application/PhabricatorHomeApplication.php', @@ -2480,6 +2483,7 @@ phutil_register_library_map(array( 'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php', 'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php', 'PhabricatorMailgunConfigOptions' => 'applications/config/option/PhabricatorMailgunConfigOptions.php', + 'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php', 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 'PhabricatorManagementWorkflow' => 'infrastructure/management/PhabricatorManagementWorkflow.php', @@ -2724,6 +2728,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php', 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', + 'PhabricatorPeopleMainMenuBarExtension' => 'applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php', 'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php', @@ -3091,6 +3096,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsAdjustController' => 'applications/settings/controller/PhabricatorSettingsAdjustController.php', 'PhabricatorSettingsApplication' => 'applications/settings/application/PhabricatorSettingsApplication.php', 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', + 'PhabricatorSettingsMainMenuBarExtension' => 'applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php', 'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', 'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', 'PhabricatorSetupCheckTestCase' => 'applications/config/check/__tests__/PhabricatorSetupCheckTestCase.php', @@ -5615,6 +5621,7 @@ phutil_register_library_map(array( 'PHUIListItemView' => 'AphrontTagView', 'PHUIListView' => 'AphrontTagView', 'PHUIListViewTestCase' => 'PhabricatorTestCase', + 'PHUIMainMenuView' => 'AphrontView', 'PHUIObjectBoxView' => 'AphrontView', 'PHUIObjectItemListExample' => 'PhabricatorUIExample', 'PHUIObjectItemListView' => 'AphrontTagView', @@ -5863,6 +5870,7 @@ phutil_register_library_map(array( 'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthLoginHandler' => 'Phobject', + 'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorAuthManagementCachePKCS8Workflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementLDAPWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementListFactorsWorkflow' => 'PhabricatorAuthManagementWorkflow', @@ -6631,6 +6639,7 @@ phutil_register_library_map(array( 'PhabricatorHelpDocumentationController' => 'PhabricatorHelpController', 'PhabricatorHelpEditorProtocolController' => 'PhabricatorHelpController', 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', + 'PhabricatorHelpMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorHeraldApplication' => 'PhabricatorApplication', 'PhabricatorHighSecurityRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorHomeApplication' => 'PhabricatorApplication', @@ -6748,6 +6757,7 @@ phutil_register_library_map(array( 'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorMailTarget' => 'Phobject', 'PhabricatorMailgunConfigOptions' => 'PhabricatorApplicationConfigOptions', + 'PhabricatorMainMenuBarExtension' => 'Phobject', 'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuView' => 'AphrontView', 'PhabricatorManagementWorkflow' => 'PhutilArgumentWorkflow', @@ -7037,6 +7047,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', + 'PhabricatorPeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', @@ -7488,6 +7499,7 @@ phutil_register_library_map(array( 'PhabricatorSettingsAdjustController' => 'PhabricatorController', 'PhabricatorSettingsApplication' => 'PhabricatorApplication', 'PhabricatorSettingsMainController' => 'PhabricatorController', + 'PhabricatorSettingsMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorSettingsPanel' => 'Phobject', 'PhabricatorSetupCheck' => 'Phobject', 'PhabricatorSetupCheckTestCase' => 'PhabricatorTestCase', diff --git a/src/applications/auth/application/PhabricatorAuthApplication.php b/src/applications/auth/application/PhabricatorAuthApplication.php index dfa1be6f75..a9831b20e3 100644 --- a/src/applications/auth/application/PhabricatorAuthApplication.php +++ b/src/applications/auth/application/PhabricatorAuthApplication.php @@ -38,48 +38,6 @@ final class PhabricatorAuthApplication extends PhabricatorApplication { return array(); } - public function buildMainMenuItems( - PhabricatorUser $user, - PhabricatorController $controller = null) { - - $items = array(); - - if ($user->isLoggedIn()) { - $item = id(new PHUIListItemView()) - ->addClass('core-menu-item') - ->setName(pht('Log Out')) - ->setIcon('fa-sign-out') - ->setWorkflow(true) - ->setHref('/logout/') - ->setSelected(($controller instanceof PhabricatorLogoutController)) - ->setAural(pht('Log Out')) - ->setOrder(900); - $items[] = $item; - } else { - if ($controller instanceof PhabricatorAuthController) { - // Don't show the "Login" item on auth controllers, since they're - // generally all related to logging in anyway. - } else { - $uri = new PhutilURI('/auth/start/'); - if ($controller) { - $path = $controller->getRequest()->getPath(); - $uri->setQueryParam('next', $path); - } - $item = id(new PHUIListItemView()) - ->addClass('core-menu-item') - ->setName(pht('Log In')) - // TODO: Login icon? - ->setIcon('fa-sign-in') - ->setHref($uri) - ->setAural(pht('Log In')) - ->setOrder(900); - $items[] = $item; - } - } - - return $items; - } - public function getApplicationGroup() { return self::GROUP_ADMIN; } diff --git a/src/applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php b/src/applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php new file mode 100644 index 0000000000..47264517e0 --- /dev/null +++ b/src/applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php @@ -0,0 +1,73 @@ +getViewer(); + + if ($viewer->isLoggedIn()) { + return array( + $this->buildLogoutMenu(), + ); + } + + $controller = $this->getController(); + if ($controller instanceof PhabricatorAuthController) { + // Don't show the "Login" item on auth controllers, since they're + // generally all related to logging in anyway. + return array(); + } + + return array( + $this->buildLoginMenu(), + ); + } + + private function buildLogoutMenu() { + $controller = $this->getController(); + + $is_selected = ($controller instanceof PhabricatorLogoutController); + + $bar_item = id(new PHUIListItemView()) + ->addClass('core-menu-item') + ->setName(pht('Log Out')) + ->setIcon('fa-sign-out') + ->setWorkflow(true) + ->setHref('/logout/') + ->setSelected($is_selected) + ->setAural(pht('Log Out')); + + return id(new PHUIMainMenuView()) + ->setOrder(900) + ->setMenuBarItem($bar_item); + } + + private function buildLoginMenu() { + $controller = $this->getController(); + + $uri = new PhutilURI('/auth/start/'); + if ($controller) { + $path = $controller->getRequest()->getPath(); + $uri->setQueryParam('next', $path); + } + + $bar_item = id(new PHUIListItemView()) + ->addClass('core-menu-item') + ->setName(pht('Log In')) + ->setIcon('fa-sign-in') + ->setHref($uri) + ->setAural(pht('Log In')); + + return id(new PHUIMainMenuView()) + ->setOrder(900) + ->setMenuBarItem($bar_item); + } + +} diff --git a/src/applications/help/application/PhabricatorHelpApplication.php b/src/applications/help/application/PhabricatorHelpApplication.php index b1f66b02cd..deeae7fa94 100644 --- a/src/applications/help/application/PhabricatorHelpApplication.php +++ b/src/applications/help/application/PhabricatorHelpApplication.php @@ -25,84 +25,4 @@ final class PhabricatorHelpApplication extends PhabricatorApplication { ); } - public function buildMainMenuItems( - PhabricatorUser $user, - PhabricatorController $controller = null) { - - $application = null; - if ($controller) { - $application = $controller->getCurrentApplication(); - } - - $items = array(); - - $help_id = celerity_generate_unique_node_id(); - - Javelin::initBehavior( - 'aphlict-dropdown', - array( - 'bubbleID' => $help_id, - 'dropdownID' => 'phabricator-help-menu', - 'applicationClass' => __CLASS__, - 'local' => true, - 'desktop' => true, - 'right' => true, - )); - - $item = id(new PHUIListItemView()) - ->setIcon('fa-life-ring') - ->addClass('core-menu-item') - ->setID($help_id) - ->setOrder(200); - - $hide = true; - if ($application) { - $help_name = pht('%s Help', $application->getName()); - $item - ->setName($help_name) - ->setHref('/help/documentation/'.get_class($application).'/') - ->setAural($help_name); - $help_items = $application->getHelpMenuItems($user); - if ($help_items) { - $hide = false; - } - } - if ($hide) { - $item->setStyle('display: none'); - } - $items[] = $item; - - return $items; - } - - public function buildMainMenuExtraNodes( - PhabricatorUser $viewer, - PhabricatorController $controller = null) { - - $application = null; - if ($controller) { - $application = $controller->getCurrentApplication(); - } - - $view = null; - if ($application) { - $help_items = $application->getHelpMenuItems($viewer); - if ($help_items) { - $view = new PHUIListView(); - foreach ($help_items as $item) { - $view->addMenuItem($item); - } - } - } - - return phutil_tag( - 'div', - array( - 'id' => 'phabricator-help-menu', - 'class' => 'phabricator-main-menu-dropdown phui-list-sidenav', - 'style' => 'display: none', - ), - $view); - } - } diff --git a/src/applications/help/extension/PhabricatorHelpMainMenuBarExtension.php b/src/applications/help/extension/PhabricatorHelpMainMenuBarExtension.php new file mode 100644 index 0000000000..f12714b5ac --- /dev/null +++ b/src/applications/help/extension/PhabricatorHelpMainMenuBarExtension.php @@ -0,0 +1,70 @@ +getApplication(); + if (!$application) { + return array(); + } + + $viewer = $this->getViewer(); + $help_links = $application->getHelpMenuItems($viewer); + if (!$help_links) { + return array(); + } + + $help_id = celerity_generate_unique_node_id(); + + Javelin::initBehavior( + 'aphlict-dropdown', + array( + 'bubbleID' => $help_id, + 'dropdownID' => 'phabricator-help-menu', + 'local' => true, + 'desktop' => true, + 'right' => true, + )); + + $help_name = pht('%s Help', $application->getName()); + + $help_item = id(new PHUIListItemView()) + ->setIcon('fa-life-ring') + ->addClass('core-menu-item') + ->setID($help_id) + ->setName($help_name) + ->setHref('/help/documentation/'.get_class($application).'/') + ->setAural($help_name); + + $view = new PHUIListView(); + foreach ($help_links as $help_link) { + $view->addMenuItem($help_link); + } + + $dropdown_menu = phutil_tag( + 'div', + array( + 'id' => 'phabricator-help-menu', + 'class' => 'phabricator-main-menu-dropdown phui-list-sidenav', + 'style' => 'display: none', + ), + $view); + + $help_menu = id(new PHUIMainMenuView()) + ->setOrder(200) + ->setMenuBarItem($help_item) + ->appendChild($dropdown_menu); + + return array( + $help_menu, + ); + } + +} diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index d1cb552e18..45599907c8 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -123,48 +123,6 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { return $status; } - public function buildMainMenuItems( - PhabricatorUser $user, - PhabricatorController $controller = null) { - - $items = array(); - - if ($user->isLoggedIn() && $user->isUserActivated()) { - $profile = id(new PhabricatorPeopleQuery()) - ->setViewer($user) - ->needProfileImage(true) - ->withPHIDs(array($user->getPHID())) - ->executeOne(); - $image = $profile->getProfileImageURI(); - - $item = id(new PHUIListItemView()) - ->setName($user->getUsername()) - ->setHref('/p/'.$user->getUsername().'/') - ->addClass('core-menu-item') - ->setAural(pht('Profile')) - ->setOrder(100); - - $classes = array( - 'phabricator-core-menu-icon', - 'phabricator-core-menu-profile-image', - ); - - $item->appendChild( - phutil_tag( - 'span', - array( - 'class' => implode(' ', $classes), - 'style' => 'background-image: url('.$image.')', - ), - '')); - - $items[] = $item; - } - - return $items; - } - - public function getQuickCreateItems(PhabricatorUser $viewer) { $items = array(); diff --git a/src/applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php b/src/applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php new file mode 100644 index 0000000000..a92c5ba235 --- /dev/null +++ b/src/applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php @@ -0,0 +1,49 @@ +getViewer(); + + // TODO: This should get cached. + + $profile = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->needProfileImage(true) + ->withPHIDs(array($viewer->getPHID())) + ->executeOne(); + $image = $profile->getProfileImageURI(); + + $bar_item = id(new PHUIListItemView()) + ->setName($viewer->getUsername()) + ->setHref('/p/'.$viewer->getUsername().'/') + ->addClass('core-menu-item') + ->setAural(pht('Profile')); + + $classes = array( + 'phabricator-core-menu-icon', + 'phabricator-core-menu-profile-image', + ); + + $bar_item->appendChild( + phutil_tag( + 'span', + array( + 'class' => implode(' ', $classes), + 'style' => 'background-image: url('.$image.')', + ), + '')); + + $profile_menu = id(new PHUIMainMenuView()) + ->setOrder(100) + ->setMenuBarItem($bar_item); + + return array( + $profile_menu, + ); + } + +} diff --git a/src/applications/settings/application/PhabricatorSettingsApplication.php b/src/applications/settings/application/PhabricatorSettingsApplication.php index da0daf65d2..2608cabd88 100644 --- a/src/applications/settings/application/PhabricatorSettingsApplication.php +++ b/src/applications/settings/application/PhabricatorSettingsApplication.php @@ -40,26 +40,4 @@ final class PhabricatorSettingsApplication extends PhabricatorApplication { return self::GROUP_UTILITIES; } - public function buildMainMenuItems( - PhabricatorUser $user, - PhabricatorController $controller = null) { - - $items = array(); - - if ($user->isLoggedIn() && $user->isUserActivated()) { - $selected = ($controller instanceof PhabricatorSettingsMainController); - $item = id(new PHUIListItemView()) - ->setName(pht('Settings')) - ->setIcon('fa-wrench') - ->addClass('core-menu-item') - ->setSelected($selected) - ->setHref('/settings/') - ->setAural(pht('Settings')) - ->setOrder(400); - $items[] = $item; - } - - return $items; - } - } diff --git a/src/applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php b/src/applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php new file mode 100644 index 0000000000..21534c4237 --- /dev/null +++ b/src/applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php @@ -0,0 +1,29 @@ +getController(); + $is_selected = ($controller instanceof PhabricatorSettingsMainController); + + $bar_item = id(new PHUIListItemView()) + ->setName(pht('Settings')) + ->setIcon('fa-wrench') + ->addClass('core-menu-item') + ->setSelected($is_selected) + ->setHref('/settings/') + ->setAural(pht('Settings')); + + $settings_menu = id(new PHUIMainMenuView()) + ->setMenuBarItem($bar_item) + ->setOrder(400); + + return array( + $settings_menu, + ); + } + +} diff --git a/src/view/page/menu/PhabricatorMainMenuBarExtension.php b/src/view/page/menu/PhabricatorMainMenuBarExtension.php new file mode 100644 index 0000000000..8b863c835c --- /dev/null +++ b/src/view/page/menu/PhabricatorMainMenuBarExtension.php @@ -0,0 +1,88 @@ +viewer = $viewer; + return $this; + } + + public function getViewer() { + return $this->viewer; + } + + public function setApplication(PhabricatorApplication $application) { + $this->application = $application; + return $this; + } + + public function getApplication() { + return $this->application; + } + + public function setController(PhabricatorController $controller) { + $this->controller = $controller; + return $this; + } + + public function getController() { + return $this->controller; + } + + final public function getExtensionKey() { + return $this->getPhobjectClassConstant('MAINMENUBARKEY'); + } + + public function isExtensionEnabled() { + return true; + } + + public function isExtensionEnabledForViewer(PhabricatorUser $viewer) { + if (!$viewer->isLoggedIn()) { + return false; + } + + if (!$viewer->isUserActivated()) { + return false; + } + + // Don't show menus for users with partial sessions. This usually means + // they have logged in but have not made it through MFA, so we don't want + // to show notification counts, saved queries, etc. + if (!$viewer->hasSession()) { + return false; + } + + if ($viewer->getSession()->getIsPartial()) { + return false; + } + + return true; + } + + abstract public function buildMainMenus(); + + final public static function getAllExtensions() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getExtensionKey') + ->execute(); + } + + final public static function getAllEnabledExtensions() { + $extensions = self::getAllExtensions(); + + foreach ($extensions as $key => $extension) { + if (!$extension->isExtensionEnabled()) { + unset($extensions[$key]); + } + } + + return $extensions; + } + +} diff --git a/src/view/page/menu/PhabricatorMainMenuView.php b/src/view/page/menu/PhabricatorMainMenuView.php index 1dc8466df3..54ba622f80 100644 --- a/src/view/page/menu/PhabricatorMainMenuView.php +++ b/src/view/page/menu/PhabricatorMainMenuView.php @@ -30,7 +30,7 @@ final class PhabricatorMainMenuView extends AphrontView { require_celerity_resource('sprite-main-header-css'); $header_id = celerity_generate_unique_node_id(); - $menus = array(); + $menu_bar = array(); $alerts = array(); $search_button = ''; $app_button = ''; @@ -41,7 +41,7 @@ final class PhabricatorMainMenuView extends AphrontView { if (array_filter($menu)) { $alerts[] = $menu; } - $menus = array_merge($menus, $dropdowns); + $menu_bar = array_merge($menu_bar, $dropdowns); $app_button = $this->renderApplicationMenuButton($header_id); $search_button = $this->renderSearchMenuButton($header_id); } else { @@ -73,13 +73,69 @@ final class PhabricatorMainMenuView extends AphrontView { } $applications = PhabricatorApplication::getAllInstalledApplications(); + + $menus = array(); + $controller = $this->getController(); foreach ($applications as $application) { - $menus[] = $application->buildMainMenuExtraNodes( + $app_actions = $application->buildMainMenuItems( $user, - $this->getController()); + $controller); + $app_extra = $application->buildMainMenuExtraNodes( + $user, + $controller); + + foreach ($app_actions as $action) { + $menus[] = id(new PHUIMainMenuView()) + ->setMenuBarItem($action) + ->setOrder($action->getOrder()); + } + + if ($app_extra !== null) { + $menus[] = id(new PHUIMainMenuView()) + ->appendChild($app_extra); + } } - $application_menu = $this->renderApplicationMenu(); + $extensions = PhabricatorMainMenuBarExtension::getAllEnabledExtensions(); + foreach ($extensions as $extension) { + $extension->setViewer($user); + + $controller = $this->getController(); + if ($controller) { + $extension->setController($controller); + $application = $controller->getCurrentApplication(); + if ($application) { + $extension->setApplication($application); + } + } + } + + foreach ($extensions as $key => $extension) { + if (!$extension->isExtensionEnabledForViewer($extension->getViewer())) { + unset($extensions[$key]); + } + } + + foreach ($extensions as $extension) { + foreach ($extension->buildMainMenus() as $menu) { + $menus[] = $menu; + } + } + + $menus = msort($menus, 'getOrder'); + $bar_items = array(); + foreach ($menus as $menu) { + $menu_bar[] = $menu; + + $item = $menu->getMenuBarItem(); + if ($item === null) { + continue; + } + + $bar_items[] = $item; + } + + $application_menu = $this->renderApplicationMenu($bar_items); $classes = array(); $classes[] = 'phabricator-main-menu sprite-main-header'; $classes[] = 'phabricator-main-menu-background'; @@ -98,7 +154,7 @@ final class PhabricatorMainMenuView extends AphrontView { $aural, $application_menu, $search_menu, - $menus, + $menu_bar, )); } @@ -174,21 +230,8 @@ final class PhabricatorMainMenuView extends AphrontView { '')); } - public function renderApplicationMenu() { + private function renderApplicationMenu(array $bar_items) { $user = $this->getUser(); - $controller = $this->getController(); - - $applications = PhabricatorApplication::getAllInstalledApplications(); - - $actions = array(); - foreach ($applications as $application) { - $app_actions = $application->buildMainMenuItems($user, $controller); - foreach ($app_actions as $action) { - $actions[] = $action; - } - } - - $actions = msort($actions, 'getOrder'); $view = $this->getApplicationMenu(); @@ -199,13 +242,13 @@ final class PhabricatorMainMenuView extends AphrontView { $view->addClass('phabricator-dark-menu'); $view->addClass('phabricator-application-menu'); - if ($actions) { + if ($bar_items) { $view->addMenuItem( id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LABEL) ->setName(pht('Actions'))); - foreach ($actions as $action) { - $view->addMenuItem($action); + foreach ($bar_items as $bar_item) { + $view->addMenuItem($bar_item); } } diff --git a/src/view/phui/PHUIMainMenuView.php b/src/view/phui/PHUIMainMenuView.php new file mode 100644 index 0000000000..7d5910dd7b --- /dev/null +++ b/src/view/phui/PHUIMainMenuView.php @@ -0,0 +1,31 @@ +menuItem = $menu_item; + return $this; + } + + public function getMenuBarItem() { + return $this->menuItem; + } + + public function setOrder($order) { + $this->order = $order; + return $this; + } + + public function getOrder() { + return $this->order; + } + + public function render() { + return $this->renderChildren(); + } + +}