@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move Favorites and User menus to MenuBarExtensions

Summary:
Ref T12140. The major effect of this change is that uninstalling "Home" (as we do on admin.phacility.com) no longer uninstalls the user menu (which is required to access settings or log out).

This also simplifies the code a bit, by consolidating how menus are built into MenuBarExtensions instead of some in Applications and some in Extensions.

Test Plan:
- While logged in and logged out, saw main menus in the correct order.
- Uninstalled Favorites, saw the menu vanish.
- Uninstalled Home, still had a user menu.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12140

Differential Revision: https://secure.phabricator.com/D17239

+231 -220
+4
src/__phutil_library_map__.php
··· 1785 1785 'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php', 1786 1786 'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php', 1787 1787 'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php', 1788 + 'PeopleMainMenuBarExtension' => 'applications/people/engineextension/PeopleMainMenuBarExtension.php', 1788 1789 'PeopleUserLogGarbageCollector' => 'applications/people/garbagecollector/PeopleUserLogGarbageCollector.php', 1789 1790 'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php', 1790 1791 'PhabricatorAWSConfigOptions' => 'applications/config/option/PhabricatorAWSConfigOptions.php', ··· 2671 2672 'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php', 2672 2673 'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php', 2673 2674 'PhabricatorFavoritesMainController' => 'applications/favorites/controller/PhabricatorFavoritesMainController.php', 2675 + 'PhabricatorFavoritesMainMenuBarExtension' => 'applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php', 2674 2676 'PhabricatorFavoritesMenuItemController' => 'applications/favorites/controller/PhabricatorFavoritesMenuItemController.php', 2675 2677 'PhabricatorFavoritesProfileMenuEngine' => 'applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php', 2676 2678 'PhabricatorFaxContentSource' => 'infrastructure/contentsource/PhabricatorFaxContentSource.php', ··· 6662 6664 'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', 6663 6665 'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', 6664 6666 'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 6667 + 'PeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 6665 6668 'PeopleUserLogGarbageCollector' => 'PhabricatorGarbageCollector', 6666 6669 'Phabricator404Controller' => 'PhabricatorController', 6667 6670 'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions', ··· 7685 7688 'PhabricatorFavoritesApplication' => 'PhabricatorApplication', 7686 7689 'PhabricatorFavoritesController' => 'PhabricatorController', 7687 7690 'PhabricatorFavoritesMainController' => 'PhabricatorFavoritesController', 7691 + 'PhabricatorFavoritesMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 7688 7692 'PhabricatorFavoritesMenuItemController' => 'PhabricatorFavoritesController', 7689 7693 'PhabricatorFavoritesProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 7690 7694 'PhabricatorFaxContentSource' => 'PhabricatorContentSource',
+4
src/applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php
··· 9 9 return true; 10 10 } 11 11 12 + public function getExtensionOrder() { 13 + return 900; 14 + } 15 + 12 16 public function buildMainMenus() { 13 17 $viewer = $this->getViewer(); 14 18
-17
src/applications/base/PhabricatorApplication.php
··· 315 315 } 316 316 317 317 318 - /** 319 - * Build extra items for the main menu. Generally, this is used to render 320 - * static dropdowns. 321 - * 322 - * @param PhabricatorUser The viewing user. 323 - * @param AphrontController The current controller. May be null for special 324 - * pages like 404, exception handlers, etc. 325 - * @return view List of menu items. 326 - * @task ui 327 - */ 328 - public function buildMainMenuExtraNodes( 329 - PhabricatorUser $viewer, 330 - PhabricatorController $controller = null) { 331 - return array(); 332 - } 333 - 334 - 335 318 /* -( Application Management )--------------------------------------------- */ 336 319 337 320
-78
src/applications/favorites/application/PhabricatorFavoritesApplication.php
··· 32 32 return false; 33 33 } 34 34 35 - public function buildMainMenuExtraNodes( 36 - PhabricatorUser $viewer, 37 - PhabricatorController $controller = null) { 38 - 39 - $dropdown = $this->renderFavoritesDropdown($viewer); 40 - if (!$dropdown) { 41 - return null; 42 - } 43 - 44 - return id(new PHUIButtonView()) 45 - ->setTag('a') 46 - ->setHref('#') 47 - ->setIcon('fa-star') 48 - ->addClass('phabricator-core-user-menu') 49 - ->setNoCSS(true) 50 - ->setDropdown(true) 51 - ->setDropdownMenu($dropdown); 52 - } 53 - 54 - private function renderFavoritesDropdown(PhabricatorUser $viewer) { 55 - $application = __CLASS__; 56 - 57 - $applications = id(new PhabricatorApplicationQuery()) 58 - ->setViewer($viewer) 59 - ->withClasses(array($application)) 60 - ->withInstalled(true) 61 - ->execute(); 62 - $favorites = head($applications); 63 - if (!$favorites) { 64 - return null; 65 - } 66 - 67 - $menu_engine = id(new PhabricatorFavoritesProfileMenuEngine()) 68 - ->setViewer($viewer) 69 - ->setProfileObject($favorites); 70 - 71 - if ($viewer->getPHID()) { 72 - $menu_engine 73 - ->setCustomPHID($viewer->getPHID()) 74 - ->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED); 75 - } else { 76 - $menu_engine 77 - ->setMenuType(PhabricatorProfileMenuEngine::MENU_GLOBAL); 78 - } 79 - 80 - $filter_view = $menu_engine->buildNavigation(); 81 - 82 - $menu_view = $filter_view->getMenu(); 83 - $item_views = $menu_view->getItems(); 84 - 85 - $view = id(new PhabricatorActionListView()) 86 - ->setViewer($viewer); 87 - foreach ($item_views as $item) { 88 - $type = null; 89 - if (!strlen($item->getName())) { 90 - $type = PhabricatorActionView::TYPE_DIVIDER; 91 - } 92 - $action = id(new PhabricatorActionView()) 93 - ->setName($item->getName()) 94 - ->setHref($item->getHref()) 95 - ->setType($type); 96 - $view->addAction($action); 97 - } 98 - 99 - // Build out edit interface 100 - if ($viewer->isLoggedIn()) { 101 - $view->addAction( 102 - id(new PhabricatorActionView()) 103 - ->setType(PhabricatorActionView::TYPE_DIVIDER)); 104 - $view->addAction( 105 - id(new PhabricatorActionView()) 106 - ->setName(pht('Edit Favorites')) 107 - ->setHref('/favorites/')); 108 - } 109 - 110 - return $view; 111 - } 112 - 113 35 }
+96
src/applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php
··· 1 + <?php 2 + 3 + final class PhabricatorFavoritesMainMenuBarExtension 4 + extends PhabricatorMainMenuBarExtension { 5 + 6 + const MAINMENUBARKEY = 'favorites'; 7 + 8 + public function isExtensionEnabledForViewer(PhabricatorUser $viewer) { 9 + return PhabricatorApplication::isClassInstalledForViewer( 10 + 'PhabricatorFavoritesApplication', 11 + $viewer); 12 + } 13 + 14 + public function getExtensionOrder() { 15 + return 1100; 16 + } 17 + 18 + public function buildMainMenus() { 19 + $viewer = $this->getViewer(); 20 + 21 + $dropdown = $this->newDropdown($viewer); 22 + if (!$dropdown) { 23 + return null; 24 + } 25 + 26 + $favorites_menu = id(new PHUIButtonView()) 27 + ->setTag('a') 28 + ->setHref('#') 29 + ->setIcon('fa-star') 30 + ->addClass('phabricator-core-user-menu') 31 + ->setNoCSS(true) 32 + ->setDropdown(true) 33 + ->setDropdownMenu($dropdown); 34 + 35 + return array( 36 + $favorites_menu, 37 + ); 38 + } 39 + 40 + private function newDropdown(PhabricatorUser $viewer) { 41 + $applications = id(new PhabricatorApplicationQuery()) 42 + ->setViewer($viewer) 43 + ->withClasses(array('PhabricatorFavoritesApplication')) 44 + ->withInstalled(true) 45 + ->execute(); 46 + $favorites = head($applications); 47 + if (!$favorites) { 48 + return null; 49 + } 50 + 51 + $menu_engine = id(new PhabricatorFavoritesProfileMenuEngine()) 52 + ->setViewer($viewer) 53 + ->setProfileObject($favorites); 54 + 55 + if ($viewer->getPHID()) { 56 + $menu_engine 57 + ->setCustomPHID($viewer->getPHID()) 58 + ->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED); 59 + } else { 60 + $menu_engine 61 + ->setMenuType(PhabricatorProfileMenuEngine::MENU_GLOBAL); 62 + } 63 + 64 + $filter_view = $menu_engine->buildNavigation(); 65 + 66 + $menu_view = $filter_view->getMenu(); 67 + $item_views = $menu_view->getItems(); 68 + 69 + $view = id(new PhabricatorActionListView()) 70 + ->setViewer($viewer); 71 + foreach ($item_views as $item) { 72 + $type = null; 73 + if (!strlen($item->getName())) { 74 + $type = PhabricatorActionView::TYPE_DIVIDER; 75 + } 76 + $action = id(new PhabricatorActionView()) 77 + ->setName($item->getName()) 78 + ->setHref($item->getHref()) 79 + ->setType($type); 80 + $view->addAction($action); 81 + } 82 + 83 + if ($viewer->isLoggedIn()) { 84 + $view->addAction( 85 + id(new PhabricatorActionView()) 86 + ->setType(PhabricatorActionView::TYPE_DIVIDER)); 87 + $view->addAction( 88 + id(new PhabricatorActionView()) 89 + ->setName(pht('Edit Favorites')) 90 + ->setHref('/favorites/')); 91 + } 92 + 93 + return $view; 94 + } 95 + 96 + }
-110
src/applications/home/application/PhabricatorHomeApplication.php
··· 42 42 return 9; 43 43 } 44 44 45 - public function buildMainMenuExtraNodes( 46 - PhabricatorUser $viewer, 47 - PhabricatorController $controller = null) { 48 - 49 - if (!$viewer->isLoggedIn()) { 50 - return; 51 - } 52 - 53 - $image = $viewer->getProfileImageURI(); 54 - 55 - $profile_image = id(new PHUIIconView()) 56 - ->setImage($image) 57 - ->setHeadSize(PHUIIconView::HEAD_SMALL); 58 - 59 - if ($controller) { 60 - $application = $controller->getCurrentApplication(); 61 - } else { 62 - $application = null; 63 - } 64 - $dropdown_menu = $this->renderUserDropdown($viewer, $application); 65 - 66 - $menu_id = celerity_generate_unique_node_id(); 67 - 68 - Javelin::initBehavior( 69 - 'user-menu', 70 - array( 71 - 'menuID' => $menu_id, 72 - 'menu' => $dropdown_menu->getDropdownMenuMetadata(), 73 - )); 74 - 75 - return id(new PHUIButtonView()) 76 - ->setID($menu_id) 77 - ->setTag('a') 78 - ->setHref('/p/'.$viewer->getUsername().'/') 79 - ->setIcon($profile_image) 80 - ->addClass('phabricator-core-user-menu') 81 - ->setHasCaret(true) 82 - ->setNoCSS(true); 83 - } 84 - 85 - private function renderUserDropdown( 86 - PhabricatorUser $viewer, 87 - $application) { 88 - 89 - $person_to_show = id(new PHUIObjectItemView()) 90 - ->setObjectName($viewer->getRealName()) 91 - ->setSubHead($viewer->getUsername()) 92 - ->setImageURI($viewer->getProfileImageURI()); 93 - 94 - $user_view = id(new PHUIObjectItemListView()) 95 - ->setViewer($viewer) 96 - ->setFlush(true) 97 - ->setSimple(true) 98 - ->addItem($person_to_show) 99 - ->addClass('phabricator-core-user-profile-object'); 100 - 101 - $view = id(new PhabricatorActionListView()) 102 - ->setViewer($viewer); 103 - 104 - // User Menu 105 - $view->addAction( 106 - id(new PhabricatorActionView()) 107 - ->appendChild($user_view)); 108 - 109 - $view->addAction( 110 - id(new PhabricatorActionView()) 111 - ->setType(PhabricatorActionView::TYPE_DIVIDER)); 112 - 113 - $view->addAction( 114 - id(new PhabricatorActionView()) 115 - ->setName(pht('Profile')) 116 - ->setHref('/p/'.$viewer->getUsername().'/')); 117 - 118 - $view->addAction( 119 - id(new PhabricatorActionView()) 120 - ->setName(pht('Settings')) 121 - ->setHref('/settings/user/'.$viewer->getUsername().'/')); 122 - 123 - $view->addAction( 124 - id(new PhabricatorActionView()) 125 - ->setName(pht('Manage')) 126 - ->setHref('/people/manage/'.$viewer->getID().'/')); 127 - 128 - // Help Menus 129 - if ($application) { 130 - $help_links = $application->getHelpMenuItems($viewer); 131 - if ($help_links) { 132 - foreach ($help_links as $link) { 133 - $view->addAction($link); 134 - } 135 - } 136 - } 137 - 138 - // Logout Menu 139 - $view->addAction( 140 - id(new PhabricatorActionView()) 141 - ->addSigil('logout-item') 142 - ->setType(PhabricatorActionView::TYPE_DIVIDER)); 143 - 144 - $view->addAction( 145 - id(new PhabricatorActionView()) 146 - ->setName(pht('Log Out %s', $viewer->getUsername())) 147 - ->addSigil('logout-item') 148 - ->setHref('/logout/') 149 - ->setColor(PhabricatorActionView::RED) 150 - ->setWorkflow(true)); 151 - 152 - return $view; 153 - } 154 - 155 45 }
+116
src/applications/people/engineextension/PeopleMainMenuBarExtension.php
··· 1 + <?php 2 + 3 + final class PeopleMainMenuBarExtension 4 + extends PhabricatorMainMenuBarExtension { 5 + 6 + const MAINMENUBARKEY = 'user'; 7 + 8 + public function isExtensionEnabledForViewer(PhabricatorUser $viewer) { 9 + return $viewer->isLoggedIn(); 10 + } 11 + 12 + public function getExtensionOrder() { 13 + return 1200; 14 + } 15 + 16 + public function buildMainMenus() { 17 + $viewer = $this->getViewer(); 18 + $application = $this->getApplication(); 19 + $dropdown_menu = $this->newDropdown($viewer, $application); 20 + 21 + $menu_id = celerity_generate_unique_node_id(); 22 + 23 + Javelin::initBehavior( 24 + 'user-menu', 25 + array( 26 + 'menuID' => $menu_id, 27 + 'menu' => $dropdown_menu->getDropdownMenuMetadata(), 28 + )); 29 + 30 + $image = $viewer->getProfileImageURI(); 31 + $profile_image = id(new PHUIIconView()) 32 + ->setImage($image) 33 + ->setHeadSize(PHUIIconView::HEAD_SMALL); 34 + 35 + $user_menu = id(new PHUIButtonView()) 36 + ->setID($menu_id) 37 + ->setTag('a') 38 + ->setHref('/p/'.$viewer->getUsername().'/') 39 + ->setIcon($profile_image) 40 + ->addClass('phabricator-core-user-menu') 41 + ->setHasCaret(true) 42 + ->setNoCSS(true); 43 + 44 + return array( 45 + $user_menu, 46 + ); 47 + } 48 + 49 + private function newDropdown( 50 + PhabricatorUser $viewer, 51 + $application) { 52 + 53 + $person_to_show = id(new PHUIObjectItemView()) 54 + ->setObjectName($viewer->getRealName()) 55 + ->setSubHead($viewer->getUsername()) 56 + ->setImageURI($viewer->getProfileImageURI()); 57 + 58 + $user_view = id(new PHUIObjectItemListView()) 59 + ->setViewer($viewer) 60 + ->setFlush(true) 61 + ->setSimple(true) 62 + ->addItem($person_to_show) 63 + ->addClass('phabricator-core-user-profile-object'); 64 + 65 + $view = id(new PhabricatorActionListView()) 66 + ->setViewer($viewer); 67 + 68 + $view->addAction( 69 + id(new PhabricatorActionView()) 70 + ->appendChild($user_view)); 71 + 72 + $view->addAction( 73 + id(new PhabricatorActionView()) 74 + ->setType(PhabricatorActionView::TYPE_DIVIDER)); 75 + 76 + $view->addAction( 77 + id(new PhabricatorActionView()) 78 + ->setName(pht('Profile')) 79 + ->setHref('/p/'.$viewer->getUsername().'/')); 80 + 81 + $view->addAction( 82 + id(new PhabricatorActionView()) 83 + ->setName(pht('Settings')) 84 + ->setHref('/settings/user/'.$viewer->getUsername().'/')); 85 + 86 + $view->addAction( 87 + id(new PhabricatorActionView()) 88 + ->setName(pht('Manage')) 89 + ->setHref('/people/manage/'.$viewer->getID().'/')); 90 + 91 + if ($application) { 92 + $help_links = $application->getHelpMenuItems($viewer); 93 + if ($help_links) { 94 + foreach ($help_links as $link) { 95 + $view->addAction($link); 96 + } 97 + } 98 + } 99 + 100 + $view->addAction( 101 + id(new PhabricatorActionView()) 102 + ->addSigil('logout-item') 103 + ->setType(PhabricatorActionView::TYPE_DIVIDER)); 104 + 105 + $view->addAction( 106 + id(new PhabricatorActionView()) 107 + ->setName(pht('Log Out %s', $viewer->getUsername())) 108 + ->addSigil('logout-item') 109 + ->setHref('/logout/') 110 + ->setColor(PhabricatorActionView::RED) 111 + ->setWorkflow(true)); 112 + 113 + return $view; 114 + } 115 + 116 + }
+5
src/view/page/menu/PhabricatorMainMenuBarExtension.php
··· 64 64 return true; 65 65 } 66 66 67 + public function getExtensionOrder() { 68 + return 1000; 69 + } 70 + 67 71 abstract public function buildMainMenus(); 68 72 69 73 final public static function getAllExtensions() { 70 74 return id(new PhutilClassMapQuery()) 71 75 ->setAncestorClass(__CLASS__) 72 76 ->setUniqueMethod('getExtensionKey') 77 + ->setSortMethod('getExtensionOrder') 73 78 ->execute(); 74 79 } 75 80
+6 -15
src/view/page/menu/PhabricatorMainMenuView.php
··· 82 82 phutil_implode_html(' ', $aural)); 83 83 } 84 84 85 - // Build out Header Menus 86 - $applications = PhabricatorApplication::getAllInstalledApplications(); 87 - 88 - $menus = array(); 89 - $controller = $this->getController(); 90 - foreach ($applications as $application) { 91 - $app_extra = $application->buildMainMenuExtraNodes( 92 - $viewer, 93 - $controller); 94 - if ($app_extra !== null) { 95 - $menus[] = $app_extra; 96 - } 97 - } 98 - 99 85 $extensions = PhabricatorMainMenuBarExtension::getAllEnabledExtensions(); 100 86 foreach ($extensions as $extension) { 101 87 $extension->setViewer($viewer); ··· 116 102 } 117 103 } 118 104 119 - // Builds out "login" button 105 + $menus = array(); 120 106 foreach ($extensions as $extension) { 121 107 foreach ($extension->buildMainMenus() as $menu) { 122 108 $menus[] = $menu; 123 109 } 124 110 } 111 + 112 + // Because we display these with "float: right", reverse their order before 113 + // rendering them into the document so that the extension order and display 114 + // order are the same. 115 + $menus = array_reverse($menus); 125 116 126 117 foreach ($menus as $menu) { 127 118 $menu_bar[] = $menu;