@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.

Replace ProfileMenu bugs with different bugs

Summary:
Ref T12174. This fixes more bugs than it creates, I think:

- Dashboards now show the whole menu.
- Project and home items now show selected state correctly.
- The "choose global vs personal" thing is now part of MenuEngine, and the same code builds it for Home and Favorites.
- Home now handles defaults correctly, I think.

Maybe regression/bad/still buggy?:

- Mobile home is now whatever the default thing was, not the menu?
- Title for dashboard content or other items that render their own content is incorrectly always "Configure Menu" (this was preexisting).

Test Plan:
- Created, edited, reordered, disabled, deleted and pinned personal and global items on home, favorites, and projects.
- Also checked User profiles.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12174

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

+298 -314
+4 -8
src/__phutil_library_map__.php
··· 1687 1687 'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', 1688 1688 'PHUIHeadThingView' => 'view/phui/PHUIHeadThingView.php', 1689 1689 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 1690 + 'PHUIHomeView' => 'applications/home/view/PHUIHomeView.php', 1690 1691 'PHUIHovercardUIExample' => 'applications/uiexample/examples/PHUIHovercardUIExample.php', 1691 1692 'PHUIHovercardView' => 'view/phui/PHUIHovercardView.php', 1692 1693 'PHUIIconCircleView' => 'view/phui/PHUIIconCircleView.php', ··· 2676 2677 'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', 2677 2678 'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php', 2678 2679 'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php', 2679 - 'PhabricatorFavoritesMainController' => 'applications/favorites/controller/PhabricatorFavoritesMainController.php', 2680 2680 'PhabricatorFavoritesMainMenuBarExtension' => 'applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php', 2681 2681 'PhabricatorFavoritesMenuItemController' => 'applications/favorites/controller/PhabricatorFavoritesMenuItemController.php', 2682 2682 'PhabricatorFavoritesProfileMenuEngine' => 'applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php', ··· 2839 2839 'PhabricatorHomeConstants' => 'applications/home/constants/PhabricatorHomeConstants.php', 2840 2840 'PhabricatorHomeController' => 'applications/home/controller/PhabricatorHomeController.php', 2841 2841 'PhabricatorHomeLauncherProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php', 2842 - 'PhabricatorHomeMainController' => 'applications/home/controller/PhabricatorHomeMainController.php', 2843 - 'PhabricatorHomeManageProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeManageProfileMenuItem.php', 2844 - 'PhabricatorHomeMenuController' => 'applications/home/controller/PhabricatorHomeMenuController.php', 2845 2842 'PhabricatorHomeMenuItemController' => 'applications/home/controller/PhabricatorHomeMenuItemController.php', 2846 2843 'PhabricatorHomeProfileMenuEngine' => 'applications/home/engine/PhabricatorHomeProfileMenuEngine.php', 2847 2844 'PhabricatorHomeProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeProfileMenuItem.php', ··· 2964 2961 'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php', 2965 2962 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 2966 2963 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 2964 + 'PhabricatorManageProfileMenuItem' => 'applications/search/menuitem/PhabricatorManageProfileMenuItem.php', 2967 2965 'PhabricatorManagementWorkflow' => 'infrastructure/management/PhabricatorManagementWorkflow.php', 2968 2966 'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php', 2969 2967 'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php', ··· 6563 6561 'PHUIHandleView' => 'AphrontView', 6564 6562 'PHUIHeadThingView' => 'AphrontTagView', 6565 6563 'PHUIHeaderView' => 'AphrontTagView', 6564 + 'PHUIHomeView' => 'AphrontTagView', 6566 6565 'PHUIHovercardUIExample' => 'PhabricatorUIExample', 6567 6566 'PHUIHovercardView' => 'AphrontTagView', 6568 6567 'PHUIIconCircleView' => 'AphrontTagView', ··· 7698 7697 'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', 7699 7698 'PhabricatorFavoritesApplication' => 'PhabricatorApplication', 7700 7699 'PhabricatorFavoritesController' => 'PhabricatorController', 7701 - 'PhabricatorFavoritesMainController' => 'PhabricatorFavoritesController', 7702 7700 'PhabricatorFavoritesMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 7703 7701 'PhabricatorFavoritesMenuItemController' => 'PhabricatorFavoritesController', 7704 7702 'PhabricatorFavoritesProfileMenuEngine' => 'PhabricatorProfileMenuEngine', ··· 7897 7895 'PhabricatorHomeConstants' => 'PhabricatorHomeController', 7898 7896 'PhabricatorHomeController' => 'PhabricatorController', 7899 7897 'PhabricatorHomeLauncherProfileMenuItem' => 'PhabricatorProfileMenuItem', 7900 - 'PhabricatorHomeMainController' => 'PhabricatorHomeController', 7901 - 'PhabricatorHomeManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 7902 - 'PhabricatorHomeMenuController' => 'PhabricatorHomeController', 7903 7898 'PhabricatorHomeMenuItemController' => 'PhabricatorHomeController', 7904 7899 'PhabricatorHomeProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 7905 7900 'PhabricatorHomeProfileMenuItem' => 'PhabricatorProfileMenuItem', ··· 8022 8017 'PhabricatorMainMenuBarExtension' => 'Phobject', 8023 8018 'PhabricatorMainMenuSearchView' => 'AphrontView', 8024 8019 'PhabricatorMainMenuView' => 'AphrontView', 8020 + 'PhabricatorManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 8025 8021 'PhabricatorManagementWorkflow' => 'PhutilArgumentWorkflow', 8026 8022 'PhabricatorManiphestApplication' => 'PhabricatorApplication', 8027 8023 'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions',
+6 -2
src/applications/base/PhabricatorApplication.php
··· 596 596 protected function getProfileMenuRouting($controller) { 597 597 $edit_route = $this->getEditRoutePattern(); 598 598 599 + $mode_route = '(?P<itemEditMode>global|custom)/'; 600 + 599 601 return array( 600 602 '(?P<itemAction>view)/(?P<itemID>[^/]+)/' => $controller, 601 603 '(?P<itemAction>hide)/(?P<itemID>[^/]+)/' => $controller, 602 604 '(?P<itemAction>default)/(?P<itemID>[^/]+)/' => $controller, 603 605 '(?P<itemAction>configure)/' => $controller, 604 - '(?P<itemAction>reorder)/' => $controller, 606 + '(?P<itemAction>configure)/'.$mode_route => $controller, 607 + '(?P<itemAction>reorder)/'.$mode_route => $controller, 605 608 '(?P<itemAction>edit)/'.$edit_route => $controller, 606 - '(?P<itemAction>new)/(?<itemKey>[^/]+)/'.$edit_route => $controller, 609 + '(?P<itemAction>new)/'.$mode_route.'(?<itemKey>[^/]+)/'.$edit_route 610 + => $controller, 607 611 '(?P<itemAction>builtin)/(?<itemID>[^/]+)/'.$edit_route 608 612 => $controller, 609 613 );
+1 -2
src/applications/favorites/application/PhabricatorFavoritesApplication.php
··· 21 21 public function getRoutes() { 22 22 return array( 23 23 '/favorites/' => array( 24 - '' => 'PhabricatorFavoritesMainController', 25 - '(?P<type>global|personal)/item/' => $this->getProfileMenuRouting( 24 + 'menu/' => $this->getProfileMenuRouting( 26 25 'PhabricatorFavoritesMenuItemController'), 27 26 ), 28 27 );
-63
src/applications/favorites/controller/PhabricatorFavoritesMainController.php
··· 1 - <?php 2 - 3 - final class PhabricatorFavoritesMainController 4 - extends PhabricatorFavoritesController { 5 - 6 - public function shouldAllowPublic() { 7 - return false; 8 - } 9 - 10 - public function handleRequest(AphrontRequest $request) { 11 - $viewer = $request->getViewer(); 12 - 13 - if (!$viewer->getIsAdmin()) { 14 - $uri = '/favorites/personal/item/configure/'; 15 - return id(new AphrontRedirectResponse())->setURI($uri); 16 - } 17 - 18 - $menu = id(new PHUIObjectItemListView()) 19 - ->setUser($viewer); 20 - 21 - $menu->addItem( 22 - id(new PHUIObjectItemView()) 23 - ->setHeader(pht('Personal Menu Items')) 24 - ->setHref($this->getApplicationURI('personal/item/configure/')) 25 - ->setImageURI($viewer->getProfileImageURI()) 26 - ->addAttribute(pht('Edit favorites for your personal account.'))); 27 - 28 - $icon = id(new PHUIIconView()) 29 - ->setIcon('fa-globe') 30 - ->setBackground('bg-blue'); 31 - 32 - $menu->addItem( 33 - id(new PHUIObjectItemView()) 34 - ->setHeader(pht('Global Menu Items')) 35 - ->setHref($this->getApplicationURI('global/item/configure/')) 36 - ->setImageIcon($icon) 37 - ->addAttribute(pht('Edit global default favorites for all users.'))); 38 - 39 - $crumbs = $this->buildApplicationCrumbs(); 40 - $crumbs->addTextCrumb(pht('Manage')); 41 - $crumbs->setBorder(true); 42 - 43 - $box = id(new PHUIObjectBoxView()) 44 - ->setObjectList($menu); 45 - 46 - $header = id(new PHUIHeaderView()) 47 - ->setHeader(pht('Manage Favorites')) 48 - ->setHeaderIcon('fa-star-o'); 49 - 50 - $view = id(new PHUITwoColumnView()) 51 - ->setHeader($header) 52 - ->setFooter(array( 53 - $box, 54 - )); 55 - 56 - return $this->newPage() 57 - ->setTitle(pht('Manage')) 58 - ->setCrumbs($crumbs) 59 - ->appendChild($view); 60 - 61 - } 62 - 63 - }
+1 -9
src/applications/favorites/controller/PhabricatorFavoritesMenuItemController.php
··· 5 5 6 6 public function handleRequest(AphrontRequest $request) { 7 7 $viewer = $this->getViewer(); 8 - $type = $request->getURIData('type'); 9 - $custom_phid = null; 10 - $menu = PhabricatorProfileMenuEngine::MENU_GLOBAL; 11 - if ($type == 'personal') { 12 - $custom_phid = $viewer->getPHID(); 13 - $menu = PhabricatorProfileMenuEngine::MENU_PERSONAL; 14 - } 15 8 16 9 $application = 'PhabricatorFavoritesApplication'; 17 10 $favorites = id(new PhabricatorApplicationQuery()) ··· 22 15 23 16 $engine = id(new PhabricatorFavoritesProfileMenuEngine()) 24 17 ->setProfileObject($favorites) 25 - ->setCustomPHID($custom_phid) 18 + ->setCustomPHID($viewer->getPHID()) 26 19 ->setController($this) 27 - ->setMenuType($menu) 28 20 ->setShowNavigation(false); 29 21 30 22 return $engine->buildResponse();
+1 -8
src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php
··· 8 8 } 9 9 10 10 public function getItemURI($path) { 11 - $object = $this->getProfileObject(); 12 - $custom = $this->getCustomPHID(); 13 - 14 - if ($custom) { 15 - return "/favorites/personal/item/{$path}"; 16 - } else { 17 - return "/favorites/global/item/{$path}"; 18 - } 11 + return "/favorites/menu/{$path}"; 19 12 } 20 13 21 14 protected function getBuiltinProfileItems($object) {
+3 -11
src/applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php
··· 50 50 51 51 $menu_engine = id(new PhabricatorFavoritesProfileMenuEngine()) 52 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 - } 53 + ->setProfileObject($favorites) 54 + ->setCustomPHID($viewer->getPHID()); 63 55 64 56 $filter_view = $menu_engine->buildNavigation(); 65 57 ··· 87 79 $view->addAction( 88 80 id(new PhabricatorActionView()) 89 81 ->setName(pht('Edit Favorites')) 90 - ->setHref('/favorites/')); 82 + ->setHref('/favorites/menu/configure/')); 91 83 } 92 84 93 85 return $view;
+3 -6
src/applications/home/application/PhabricatorHomeApplication.php
··· 22 22 23 23 public function getRoutes() { 24 24 return array( 25 - '/' => 'PhabricatorHomeMainController', 26 - '/(?P<only>home)/' => 'PhabricatorHomeMainController', 25 + '/' => 'PhabricatorHomeMenuItemController', 27 26 '/home/' => array( 28 - 'menu/' => array( 29 - '' => 'PhabricatorHomeMenuController', 30 - '(?P<type>global|personal)/item/' => $this->getProfileMenuRouting( 27 + '' => 'PhabricatorHomeMenuItemController', 28 + 'menu/' => $this->getProfileMenuRouting( 31 29 'PhabricatorHomeMenuItemController'), 32 - ), 33 30 ), 34 31 ); 35 32 }
+2 -8
src/applications/home/controller/PhabricatorHomeController.php
··· 31 31 32 32 $engine = id(new PhabricatorHomeProfileMenuEngine()) 33 33 ->setViewer($viewer) 34 - ->setProfileObject($home); 35 - 36 - if ($viewer->getPHID()) { 37 - $engine->setCustomPHID($viewer->getPHID()) 38 - ->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED); 39 - } else { 40 - $engine->setMenuType(PhabricatorProfileMenuEngine::MENU_GLOBAL); 41 - } 34 + ->setProfileObject($home) 35 + ->setCustomPHID($viewer->getPHID()); 42 36 43 37 $this->profileMenu = $engine->buildNavigation(); 44 38 }
+12 -41
src/applications/home/controller/PhabricatorHomeMainController.php src/applications/home/view/PHUIHomeView.php
··· 1 1 <?php 2 2 3 - final class PhabricatorHomeMainController extends PhabricatorHomeController { 3 + final class PHUIHomeView 4 + extends AphrontTagView { 4 5 5 - public function shouldAllowPublic() { 6 - return true; 6 + protected function getTagName() { 7 + return null; 7 8 } 8 9 9 - public function isGlobalDragAndDropUploadEnabled() { 10 - return true; 10 + protected function getTagAttributes() { 11 + return array(); 11 12 } 12 13 13 - public function handleRequest(AphrontRequest $request) { 14 - $viewer = $request->getViewer(); 14 + protected function getTagContent() { 15 + $viewer = $this->getViewer(); 15 16 16 - $dashboard = PhabricatorDashboardInstall::getDashboard( 17 - $viewer, 18 - $viewer->getPHID(), 19 - get_class($this->getCurrentApplication())); 20 - 21 - if (!$dashboard) { 22 - $dashboard = PhabricatorDashboardInstall::getDashboard( 23 - $viewer, 24 - PhabricatorHomeApplication::DASHBOARD_DEFAULT, 25 - get_class($this->getCurrentApplication())); 26 - } 27 - 28 - if ($dashboard) { 29 - $content = id(new PhabricatorDashboardRenderingEngine()) 30 - ->setViewer($viewer) 31 - ->setDashboard($dashboard) 32 - ->renderDashboard(); 33 - } else { 34 - $content = $this->buildMainResponse(); 35 - } 36 - 37 - $nav = $this->getProfileMenu(); 38 - $content = 39 - array( 40 - $content, 41 - id(new PhabricatorGlobalUploadTargetView())->setUser($viewer), 42 - ); 43 - 44 - return $this->newPage() 45 - ->setTitle('Phabricator') 46 - ->addClass('phabricator-home') 47 - ->setNavigation($nav) 48 - ->appendChild($content); 49 - 17 + return array( 18 + $this->buildMainResponse(), 19 + id(new PhabricatorGlobalUploadTargetView())->setUser($viewer), 20 + ); 50 21 } 51 22 52 23 private function buildMainResponse() {
-62
src/applications/home/controller/PhabricatorHomeMenuController.php
··· 1 - <?php 2 - 3 - final class PhabricatorHomeMenuController extends PhabricatorHomeController { 4 - 5 - public function shouldAllowPublic() { 6 - return false; 7 - } 8 - 9 - public function handleRequest(AphrontRequest $request) { 10 - $viewer = $request->getViewer(); 11 - 12 - if (!$viewer->getIsAdmin()) { 13 - $uri = '/home/menu/personal/item/configure/'; 14 - return id(new AphrontRedirectResponse())->setURI($uri); 15 - } 16 - 17 - $menu = id(new PHUIObjectItemListView()) 18 - ->setUser($viewer); 19 - 20 - $menu->addItem( 21 - id(new PHUIObjectItemView()) 22 - ->setHeader(pht('Personal Menu Items')) 23 - ->setHref($this->getApplicationURI('menu/personal/item/configure/')) 24 - ->setImageURI($viewer->getProfileImageURI()) 25 - ->addAttribute(pht('Edit the menu for your personal account.'))); 26 - 27 - $icon = id(new PHUIIconView()) 28 - ->setIcon('fa-globe') 29 - ->setBackground('bg-blue'); 30 - 31 - $menu->addItem( 32 - id(new PHUIObjectItemView()) 33 - ->setHeader(pht('Global Menu Items')) 34 - ->setHref($this->getApplicationURI('menu/global/item/configure/')) 35 - ->setImageIcon($icon) 36 - ->addAttribute(pht('Edit the global default menu for all users.'))); 37 - 38 - $crumbs = $this->buildApplicationCrumbs(); 39 - $crumbs->addTextCrumb(pht('Manage')); 40 - $crumbs->setBorder(true); 41 - 42 - $box = id(new PHUIObjectBoxView()) 43 - ->setObjectList($menu); 44 - 45 - $header = id(new PHUIHeaderView()) 46 - ->setHeader(pht('Manage Home Menu')) 47 - ->setHeaderIcon('fa-home'); 48 - 49 - $view = id(new PHUITwoColumnView()) 50 - ->setHeader($header) 51 - ->setFooter(array( 52 - $box, 53 - )); 54 - 55 - return $this->newPage() 56 - ->setTitle(pht('Manage Home Menu')) 57 - ->setCrumbs($crumbs) 58 - ->appendChild($view); 59 - 60 - } 61 - 62 - }
+12 -6
src/applications/home/controller/PhabricatorHomeMenuItemController.php
··· 3 3 final class PhabricatorHomeMenuItemController 4 4 extends PhabricatorHomeController { 5 5 6 + public function shouldAllowPublic() { 7 + return true; 8 + } 9 + 10 + public function isGlobalDragAndDropUploadEnabled() { 11 + return true; 12 + } 13 + 6 14 public function handleRequest(AphrontRequest $request) { 7 15 $viewer = $this->getViewer(); 8 - $type = $request->getURIData('type'); 9 - $custom_phid = null; 10 - $menu = PhabricatorProfileMenuEngine::MENU_GLOBAL; 11 - if ($type == 'personal') { 16 + 17 + if ($viewer->getPHID()) { 12 18 $custom_phid = $viewer->getPHID(); 13 - $menu = PhabricatorProfileMenuEngine::MENU_PERSONAL; 19 + } else { 20 + $custom_phid = null; 14 21 } 15 22 16 23 $application = 'PhabricatorHomeApplication'; ··· 23 30 $engine = id(new PhabricatorHomeProfileMenuEngine()) 24 31 ->setProfileObject($home_app) 25 32 ->setCustomPHID($custom_phid) 26 - ->setMenuType($menu) 27 33 ->setController($this); 28 34 29 35 return $engine->buildResponse();
+2 -13
src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php
··· 8 8 } 9 9 10 10 public function getItemURI($path) { 11 - $object = $this->getProfileObject(); 12 - $custom = $this->getCustomPHID(); 13 - 14 - if ($custom) { 15 - return "/home/menu/personal/item/{$path}"; 16 - } else { 17 - return "/home/menu/global/item/{$path}"; 18 - } 11 + return "/home/menu/{$path}"; 19 12 } 20 13 21 14 protected function getBuiltinProfileItems($object) { ··· 58 51 ->setMenuItemKey( 59 52 PhabricatorHomeLauncherProfileMenuItem::MENUITEMKEY); 60 53 61 - // Single Manage Item, switches URI based on admin/user 62 - $items[] = $this->newItem() 63 - ->setBuiltinKey(PhabricatorHomeConstants::ITEM_MANAGE) 64 - ->setMenuItemKey( 65 - PhabricatorHomeManageProfileMenuItem::MENUITEMKEY); 54 + $items[] = $this->newManageItem(); 66 55 67 56 return $items; 68 57 }
+16 -12
src/applications/home/menuitem/PhabricatorHomeManageProfileMenuItem.php src/applications/search/menuitem/PhabricatorManageProfileMenuItem.php
··· 1 1 <?php 2 2 3 - final class PhabricatorHomeManageProfileMenuItem 3 + final class PhabricatorManageProfileMenuItem 4 4 extends PhabricatorProfileMenuItem { 5 5 6 - const MENUITEMKEY = 'home.manage.menu'; 6 + const MENUITEMKEY = 'menu.manage'; 7 7 8 8 public function getMenuItemTypeName() { 9 - return pht('Manage Home Menu'); 9 + return pht('Manage Menu'); 10 10 } 11 11 12 12 private function getDefaultName() { ··· 49 49 PhabricatorProfileMenuItemConfiguration $config) { 50 50 $viewer = $this->getViewer(); 51 51 52 - if ($viewer->isLoggedIn()) { 53 - $name = $this->getDisplayName($config); 54 - $icon = 'fa-pencil'; 55 - $href = '/home/menu/'; 56 - 57 - $item = $this->newItem() 58 - ->setHref($href) 59 - ->setName($name) 60 - ->setIcon($icon); 52 + if (!$viewer->isLoggedIn()) { 53 + return array(); 61 54 } 55 + 56 + $engine = $this->getEngine(); 57 + $href = $engine->getItemURI('configure/'); 58 + 59 + $name = $this->getDisplayName($config); 60 + $icon = 'fa-pencil'; 61 + 62 + $item = $this->newItem() 63 + ->setHref($href) 64 + ->setName($name) 65 + ->setIcon($icon); 62 66 63 67 return array( 64 68 $item,
+8 -1
src/applications/home/menuitem/PhabricatorHomeProfileMenuItem.php
··· 34 34 return $this->getDefaultName(); 35 35 } 36 36 37 + public function newPageContent() { 38 + $viewer = $this->getViewer(); 39 + 40 + return id(new PHUIHomeView()) 41 + ->setViewer($viewer); 42 + } 43 + 37 44 public function buildEditEngineFields( 38 45 PhabricatorProfileMenuItemConfiguration $config) { 39 46 return array( ··· 52 59 if ($viewer->isLoggedIn()) { 53 60 $name = $this->getDisplayName($config); 54 61 $icon = 'fa-home'; 55 - $href = '/home/'; 62 + $href = $this->getItemViewURI($config); 56 63 57 64 $item = $this->newItem() 58 65 ->setHref($href)
+5 -3
src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php
··· 7 7 return true; 8 8 } 9 9 10 + protected function isMenuEnginePersonalizable() { 11 + return false; 12 + } 13 + 10 14 public function getItemURI($path) { 11 15 $project = $this->getProfileObject(); 12 16 $id = $project->getID(); ··· 37 41 ->setMenuItemKey( 38 42 PhabricatorProjectSubprojectsProfileMenuItem::MENUITEMKEY); 39 43 40 - $items[] = $this->newItem() 41 - ->setBuiltinKey(PhabricatorProject::ITEM_MANAGE) 42 - ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY); 44 + $items[] = $this->newManageItem(); 43 45 44 46 return $items; 45 47 }
+209 -57
src/applications/search/engine/PhabricatorProfileMenuEngine.php
··· 6 6 private $profileObject; 7 7 private $customPHID; 8 8 private $items; 9 - private $menuType = self::MENU_GLOBAL; 10 9 private $defaultItem; 11 10 private $controller; 12 11 private $navigation; 13 12 private $showNavigation = true; 13 + private $editMode; 14 14 15 - const MENU_GLOBAL = 'global'; 16 - const MENU_PERSONAL = 'personal'; 17 - const MENU_COMBINED = 'menu'; 18 15 const ITEM_CUSTOM_DIVIDER = 'engine.divider'; 16 + const ITEM_MANAGE = 'item.configure'; 17 + 18 + const MODE_COMBINED = 'combined'; 19 + const MODE_GLOBAL = 'global'; 20 + const MODE_CUSTOM = 'custom'; 19 21 20 22 public function setViewer(PhabricatorUser $viewer) { 21 23 $this->viewer = $viewer; ··· 44 46 return $this->customPHID; 45 47 } 46 48 49 + private function getEditModeCustomPHID() { 50 + $mode = $this->getEditMode(); 51 + 52 + switch ($mode) { 53 + case self::MODE_CUSTOM: 54 + $custom_phid = $this->getCustomPHID(); 55 + break; 56 + case self::MODE_GLOBAL: 57 + $custom_phid = null; 58 + break; 59 + } 60 + 61 + return $custom_phid; 62 + } 63 + 47 64 public function setController(PhabricatorController $controller) { 48 65 $this->controller = $controller; 49 66 return $this; ··· 60 77 } 61 78 62 79 public function getDefaultItem() { 63 - $this->loadItems(); 80 + $this->getItems(); 64 81 return $this->defaultItem; 65 82 } 66 83 67 - public function setMenuType($type) { 68 - $this->menuType = $type; 69 - return $this; 70 - } 71 - 72 - private function getMenuType() { 73 - return $this->menuType; 74 - } 75 - 76 84 public function setShowNavigation($show) { 77 85 $this->showNavigation = $show; 78 86 return $this; ··· 91 99 $object, 92 100 $custom_phid) { 93 101 return array(); 102 + } 103 + 104 + protected function getEditMode() { 105 + return $this->editMode; 94 106 } 95 107 96 108 public function buildResponse() { ··· 171 183 172 184 $crumbs = $controller->buildApplicationCrumbsForEditEngine(); 173 185 174 - // TODO: This stuff might need a little tweaking at some point, since it 175 - // causes "Global" and "Personal" to show up in contexts where they don't 176 - // make sense, notably Projects. 177 186 if ($item_action != 'view') { 178 - $navigation->selectFilter('item.configure'); 179 - switch ($this->getMenuType()) { 180 - case 'personal': 181 - $crumbs->addTextCrumb(pht('Personal')); 182 - break; 183 - case 'global': 184 - $crumbs->addTextCrumb(pht('Global')); 185 - break; 187 + $navigation->selectFilter(self::ITEM_MANAGE); 188 + 189 + if ($selected_item) { 190 + if ($selected_item->getCustomPHID()) { 191 + $edit_mode = 'custom'; 192 + } else { 193 + $edit_mode = 'global'; 194 + } 195 + } else { 196 + $edit_mode = $request->getURIData('itemEditMode'); 197 + } 198 + 199 + $available_modes = $this->getViewerEditModes($viewer); 200 + if ($available_modes) { 201 + $available_modes = array_fuse($available_modes); 202 + if (isset($available_modes[$edit_mode])) { 203 + $this->editMode = $edit_mode; 204 + } else { 205 + if ($item_action != 'configure') { 206 + return new Aphront404Response(); 207 + } 208 + } 186 209 } 187 210 } 188 211 189 212 switch ($item_action) { 190 213 case 'view': 191 - $navigation->selectFilter($selected_item->getItemIdentifier()); 214 + $navigation->selectFilter($selected_item->getDefaultMenuItemKey()); 192 215 193 216 $content = $this->buildItemViewContent($selected_item); 194 217 $crumbs->addTextCrumb($selected_item->getDisplayName()); ··· 197 220 } 198 221 break; 199 222 case 'configure': 200 - $content = $this->buildItemConfigureContent($item_list); 201 - $crumbs->addTextCrumb(pht('Configure Menu')); 223 + $mode = $this->getEditMode(); 224 + if (!$mode) { 225 + $crumbs->addTextCrumb(pht('Configure Menu')); 226 + $content = $this->buildMenuEditModeContent(); 227 + } else { 228 + if (count($available_modes) > 1) { 229 + $crumbs->addTextCrumb( 230 + pht('Configure Menu'), 231 + $this->getItemURI('configure/')); 232 + 233 + switch ($mode) { 234 + case self::MODE_CUSTOM: 235 + $crumbs->addTextCrumb(pht('Personal')); 236 + break; 237 + case self::MODE_GLOBAL: 238 + $crumbs->addTextCrumb(pht('Global')); 239 + break; 240 + } 241 + } else { 242 + $crumbs->addTextCrumb(pht('Configure Menu')); 243 + } 244 + $edit_list = $this->loadItems($mode); 245 + $content = $this->buildItemConfigureContent($edit_list); 246 + } 202 247 break; 203 248 case 'reorder': 204 - $content = $this->buildItemReorderContent($item_list); 249 + $mode = $this->getEditMode(); 250 + $edit_list = $this->loadItems($mode); 251 + $content = $this->buildItemReorderContent($edit_list); 205 252 break; 206 253 case 'new': 207 254 $item_key = $request->getURIData('itemKey'); 208 - $content = $this->buildItemNewContent($item_key); 255 + $mode = $this->getEditMode(); 256 + $content = $this->buildItemNewContent($item_key, $mode); 209 257 break; 210 258 case 'builtin': 211 259 $content = $this->buildItemBuiltinContent($selected_item); ··· 238 286 239 287 $crumbs->setBorder(true); 240 288 289 + // TODO: This title is not correct when viewing items. 290 + 241 291 $page = $controller->newPage() 242 292 ->setTitle(pht('Configure Menu')) 243 293 ->setCrumbs($crumbs) ··· 290 340 if (count($items) == 1) { 291 341 $item = head($items); 292 342 if ($item->getKey() === null) { 293 - $item_identifier = $menu_item->getItemIdentifier(); 294 - $item->setKey($item_identifier); 343 + $default_key = $menu_item->getDefaultMenuItemKey(); 344 + $item->setKey($default_key); 295 345 } 296 346 } 297 347 ··· 308 358 309 359 private function getItems() { 310 360 if ($this->items === null) { 311 - $this->items = $this->loadItems(); 361 + $this->items = $this->loadItems(self::MODE_COMBINED); 312 362 } 313 363 314 364 return $this->items; 315 365 } 316 366 317 - private function loadItems() { 367 + private function loadItems($mode) { 318 368 $viewer = $this->getViewer(); 319 369 $object = $this->getProfileObject(); 320 370 321 - $items = $this->loadBuiltinProfileItems(); 371 + $items = $this->loadBuiltinProfileItems($mode); 322 372 323 373 $query = id(new PhabricatorProfileMenuItemConfigurationQuery()) 324 374 ->setViewer($viewer) 325 375 ->withProfilePHIDs(array($object->getPHID())); 326 376 327 - $menu_type = $this->getMenuType(); 328 - switch ($menu_type) { 329 - case self::MENU_GLOBAL: 377 + switch ($mode) { 378 + case self::MODE_GLOBAL: 330 379 $query->withCustomPHIDs(array(), true); 331 380 break; 332 - case self::MENU_PERSONAL: 381 + case self::MODE_CUSTOM: 333 382 $query->withCustomPHIDs(array($this->getCustomPHID()), false); 334 383 break; 335 - case self::MENU_COMBINED: 384 + case self::MODE_COMBINED: 336 385 $query->withCustomPHIDs(array($this->getCustomPHID()), true); 337 386 break; 338 387 } ··· 368 417 } 369 418 } 370 419 371 - $items = $this->arrangeItems($items); 420 + $items = $this->arrangeItems($items, $mode); 372 421 373 422 // Make sure exactly one valid item is marked as default. 374 423 $default = null; ··· 399 448 return $items; 400 449 } 401 450 402 - private function loadBuiltinProfileItems() { 451 + private function loadBuiltinProfileItems($mode) { 403 452 $object = $this->getProfileObject(); 404 453 405 - $menu_type = $this->getMenuType(); 406 - switch ($menu_type) { 407 - case self::MENU_GLOBAL: 454 + switch ($mode) { 455 + case self::MODE_GLOBAL: 408 456 $builtins = $this->getBuiltinProfileItems($object); 409 457 break; 410 - case self::MENU_PERSONAL: 458 + case self::MODE_CUSTOM: 411 459 $builtins = $this->getBuiltinCustomProfileItems( 412 460 $object, 413 461 $this->getCustomPHID()); 414 462 break; 415 - case self::MENU_COMBINED: 463 + case self::MODE_COMBINED: 416 464 $builtins = array(); 417 465 $builtins[] = $this->getBuiltinCustomProfileItems( 418 466 $object, ··· 489 537 } 490 538 491 539 public function getConfigureURI() { 540 + $mode = $this->getEditMode(); 541 + 542 + switch ($mode) { 543 + case self::MODE_CUSTOM: 544 + return $this->getItemURI('configure/custom/'); 545 + case self::MODE_GLOBAL: 546 + return $this->getItemURI('configure/global/'); 547 + } 548 + 492 549 return $this->getItemURI('configure/'); 493 550 } 494 551 ··· 500 557 // object the menu appears on. If you're reordering custom items, you only 501 558 // need to be able to edit the custom object. Currently, the custom object 502 559 // is always the viewing user's own user object. 503 - $custom_phid = $this->getCustomPHID(); 560 + $custom_phid = $this->getEditModeCustomPHID(); 561 + 504 562 if (!$custom_phid) { 505 563 PhabricatorPolicyFilter::requireCapability( 506 564 $viewer, ··· 593 651 return $item->newPageContent(); 594 652 } 595 653 654 + private function getViewerEditModes() { 655 + $modes = array(); 656 + 657 + $viewer = $this->getViewer(); 658 + 659 + if ($viewer->isLoggedIn() && $this->isMenuEnginePersonalizable()) { 660 + $modes[] = self::MODE_CUSTOM; 661 + } 662 + 663 + $object = $this->getProfileObject(); 664 + $can_edit = PhabricatorPolicyFilter::hasCapability( 665 + $viewer, 666 + $object, 667 + PhabricatorPolicyCapability::CAN_EDIT); 668 + 669 + if ($can_edit) { 670 + $modes[] = self::MODE_GLOBAL; 671 + } 672 + 673 + return $modes; 674 + } 675 + 676 + protected function isMenuEnginePersonalizable() { 677 + return true; 678 + } 679 + 680 + private function buildMenuEditModeContent() { 681 + $viewer = $this->getViewer(); 682 + 683 + $modes = $this->getViewerEditModes($viewer); 684 + if (!$modes) { 685 + return new Aphront404Response(); 686 + } 687 + 688 + if (count($modes) == 1) { 689 + $mode = head($modes); 690 + return id(new AphrontRedirectResponse()) 691 + ->setURI($this->getItemURI("configure/{$mode}/")); 692 + } 693 + 694 + $menu = id(new PHUIObjectItemListView()) 695 + ->setUser($viewer); 696 + 697 + $modes = array_fuse($modes); 698 + 699 + if (isset($modes['custom'])) { 700 + $menu->addItem( 701 + id(new PHUIObjectItemView()) 702 + ->setHeader(pht('Personal Menu Items')) 703 + ->setHref($this->getItemURI('configure/custom/')) 704 + ->setImageURI($viewer->getProfileImageURI()) 705 + ->addAttribute(pht('Edit the menu for your personal account.'))); 706 + } 707 + 708 + if (isset($modes['global'])) { 709 + $icon = id(new PHUIIconView()) 710 + ->setIcon('fa-globe') 711 + ->setBackground('bg-blue'); 712 + 713 + $menu->addItem( 714 + id(new PHUIObjectItemView()) 715 + ->setHeader(pht('Global Menu Items')) 716 + ->setHref($this->getItemURI('configure/global/')) 717 + ->setImageIcon($icon) 718 + ->addAttribute(pht('Edit the global default menu for all users.'))); 719 + } 720 + 721 + $box = id(new PHUIObjectBoxView()) 722 + ->setObjectList($menu); 723 + 724 + $header = id(new PHUIHeaderView()) 725 + ->setHeader(pht('Manage Menu')) 726 + ->setHeaderIcon('fa-list'); 727 + 728 + return id(new PHUITwoColumnView()) 729 + ->setHeader($header) 730 + ->setFooter($box); 731 + } 732 + 596 733 private function buildItemConfigureContent(array $items) { 597 734 $viewer = $this->getViewer(); 598 735 $object = $this->getProfileObject(); ··· 616 753 617 754 $list_id = celerity_generate_unique_node_id(); 618 755 756 + $mode = $this->getEditMode(); 757 + 619 758 Javelin::initBehavior( 620 759 'reorder-profile-menu-items', 621 760 array( 622 761 'listID' => $list_id, 623 - 'orderURI' => $this->getItemURI('reorder/'), 762 + 'orderURI' => $this->getItemURI("reorder/{$mode}/"), 624 763 )); 625 764 626 765 $list = id(new PHUIObjectItemListView()) ··· 738 877 } 739 878 740 879 $item_key = $item_type->getMenuItemKey(); 880 + $edit_mode = $this->getEditMode(); 741 881 742 882 $action_list->addAction( 743 883 id(new PhabricatorActionView()) 744 884 ->setIcon($item_type->getMenuItemTypeIcon()) 745 885 ->setName($item_type->getMenuItemTypeName()) 746 - ->setHref($this->getItemURI("new/{$item_key}/")) 886 + ->setHref($this->getItemURI("new/{$edit_mode}/{$item_key}/")) 747 887 ->setWorkflow(true)); 748 888 } 749 889 ··· 788 928 return $view; 789 929 } 790 930 791 - private function buildItemNewContent($item_key) { 931 + private function buildItemNewContent($item_key, $mode) { 792 932 $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); 793 933 $item_type = idx($item_types, $item_key); 794 934 if (!$item_type) { ··· 800 940 return new Aphront404Response(); 801 941 } 802 942 803 - $custom_phid = $this->getCustomPHID(); 943 + $custom_phid = $this->getEditModeCustomPHID(); 944 + 804 945 $configuration = PhabricatorProfileMenuItemConfiguration::initializeNewItem( 805 946 $object, 806 947 $item_type, ··· 828 969 $viewer = $this->getViewer(); 829 970 $object = $this->getProfileObject(); 830 971 $controller = $this->getController(); 972 + $custom_phid = $this->getEditModeCustomPHID(); 831 973 832 974 return id(new PhabricatorProfileMenuEditEngine()) 833 975 ->setMenuEngine($this) 834 976 ->setProfileObject($object) 835 977 ->setController($controller) 836 - ->setCustomPHID($this->getCustomPHID()) 978 + ->setCustomPHID($custom_phid) 837 979 ->buildResponse(); 838 980 } 839 981 ··· 859 1001 860 1002 $object = $this->getProfileObject(); 861 1003 $controller = $this->getController(); 1004 + $custom_phid = $this->getEditModeCustomPHID(); 862 1005 863 1006 return id(new PhabricatorProfileMenuEditEngine()) 864 1007 ->setIsBuiltin(true) ··· 866 1009 ->setProfileObject($object) 867 1010 ->setNewMenuItemConfiguration($configuration) 868 1011 ->setController($controller) 869 - ->setCustomPHID($this->getCustomPHID()) 1012 + ->setCustomPHID($custom_phid) 870 1013 ->buildResponse(); 871 1014 } 872 1015 ··· 1008 1151 return PhabricatorProfileMenuItemConfiguration::initializeNewBuiltin(); 1009 1152 } 1010 1153 1154 + protected function newManageItem() { 1155 + return $this->newItem() 1156 + ->setBuiltinKey(self::ITEM_MANAGE) 1157 + ->setMenuItemKey(PhabricatorManageProfileMenuItem::MENUITEMKEY); 1158 + } 1159 + 1011 1160 public function adjustDefault($key) { 1012 1161 $controller = $this->getController(); 1013 1162 $request = $controller->getRequest(); 1014 1163 $viewer = $request->getViewer(); 1015 1164 1016 - $items = $this->loadItems(); 1165 + $items = $this->loadItems(self::MODE_COMBINED); 1017 1166 1018 1167 // To adjust the default item, we first change any existing items that 1019 1168 // are marked as defaults to "visible", then make the new default item ··· 1074 1223 return $this; 1075 1224 } 1076 1225 1077 - private function arrangeItems(array $items) { 1226 + private function arrangeItems(array $items, $mode) { 1078 1227 // Sort the items. 1079 1228 $items = msortv($items, 'getSortVector'); 1080 1229 1230 + $object = $this->getProfileObject(); 1231 + 1081 1232 // If we have some global items and some custom items and are in "combined" 1082 1233 // mode, put a hard-coded divider item between them. 1083 - if ($this->getMenuType() == self::MENU_COMBINED) { 1234 + if ($mode == self::MODE_COMBINED) { 1084 1235 $list = array(); 1085 1236 $seen_custom = false; 1086 1237 $seen_global = false; ··· 1092 1243 $list[] = $this->newItem() 1093 1244 ->setBuiltinKey(self::ITEM_CUSTOM_DIVIDER) 1094 1245 ->setMenuItemKey(PhabricatorDividerProfileMenuItem::MENUITEMKEY) 1246 + ->attachProfileObject($object) 1095 1247 ->attachMenuItem( 1096 1248 new PhabricatorDividerProfileMenuItem()); 1097 1249 }
+4 -2
src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
··· 60 60 } 61 61 62 62 $engine = id(new PhabricatorDashboardRenderingEngine()) 63 - ->setViewer($viewer) 64 - ->setDashboard($dashboard); 63 + ->setViewer($viewer) 64 + ->setDashboard($dashboard); 65 65 66 66 return $engine->renderDashboard(); 67 67 } ··· 89 89 public function getDisplayName( 90 90 PhabricatorProfileMenuItemConfiguration $config) { 91 91 $dashboard = $this->getDashboard(); 92 + 92 93 if (!$dashboard) { 93 94 return pht('(Restricted/Invalid Dashboard)'); 94 95 } 96 + 95 97 if (strlen($this->getName($config))) { 96 98 return $this->getName($config); 97 99 } else {
+1
src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
··· 117 117 unset($page[$key]); 118 118 continue; 119 119 } 120 + 120 121 $item->attachProfileObject($profile); 121 122 } 122 123
+8
src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php
··· 195 195 return $this->getBuiltinKey(); 196 196 } 197 197 198 + public function getDefaultMenuItemKey() { 199 + if ($this->getBuiltinKey()) { 200 + return $this->getBuiltinKey(); 201 + } 202 + 203 + return $this->getPHID(); 204 + } 205 + 198 206 public function newPageContent() { 199 207 return $this->getMenuItem()->newPageContent($this); 200 208 }