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

Load global and custom profile menu items in a single query

Summary: Ref T5867. Use a single query to load both personal and global items, then reorder them and add a divider if both groups have some stuff.

Test Plan: Viewed menu, edited personal and global items, viewed/edited existing project menus.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T5867

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

+161 -77
+13 -4
src/applications/favorites/application/PhabricatorFavoritesApplication.php
··· 55 55 ->withInstalled(true) 56 56 ->executeOne(); 57 57 58 - $filter_view = id(new PhabricatorFavoritesProfileMenuEngine()) 58 + $menu_engine = id(new PhabricatorFavoritesProfileMenuEngine()) 59 59 ->setViewer($viewer) 60 - ->setProfileObject($favorites) 61 - ->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED) 62 - ->buildNavigation(); 60 + ->setProfileObject($favorites); 61 + 62 + if ($viewer->getPHID()) { 63 + $menu_engine 64 + ->setCustomPHID($viewer->getPHID()) 65 + ->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED); 66 + } else { 67 + $menu_engine 68 + ->setMenuType(PhabricatorProfileMenuEngine::MENU_GLOBAL); 69 + } 70 + 71 + $filter_view = $menu_engine->buildNavigation(); 63 72 64 73 $menu_view = $filter_view->getMenu(); 65 74 $item_views = $menu_view->getItems();
+27 -31
src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php
··· 20 20 21 21 protected function getBuiltinProfileItems($object) { 22 22 $items = array(); 23 - $custom_phid = $this->getCustomPHID(); 24 23 $viewer = $this->getViewer(); 25 24 26 - // Built-in Global Defaults 27 - if (!$custom_phid) { 28 - $create_task = array( 29 - 'name' => null, 30 - 'formKey' => 31 - id(new ManiphestEditEngine())->getProfileMenuItemDefault(), 32 - ); 25 + $create_task = array( 26 + 'name' => null, 27 + 'formKey' => 28 + id(new ManiphestEditEngine())->getProfileMenuItemDefault(), 29 + ); 33 30 34 - $create_project = array( 35 - 'name' => null, 36 - 'formKey' => 37 - id(new PhabricatorProjectEditEngine())->getProfileMenuItemDefault(), 38 - ); 31 + $create_project = array( 32 + 'name' => null, 33 + 'formKey' => 34 + id(new PhabricatorProjectEditEngine())->getProfileMenuItemDefault(), 35 + ); 39 36 40 - $create_repository = array( 41 - 'name' => null, 42 - 'formKey' => 43 - id(new DiffusionRepositoryEditEngine())->getProfileMenuItemDefault(), 44 - ); 37 + $create_repository = array( 38 + 'name' => null, 39 + 'formKey' => 40 + id(new DiffusionRepositoryEditEngine())->getProfileMenuItemDefault(), 41 + ); 45 42 46 - $items[] = $this->newItem() 47 - ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_TASK) 48 - ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 49 - ->setMenuItemProperties($create_task); 43 + $items[] = $this->newItem() 44 + ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_TASK) 45 + ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 46 + ->setMenuItemProperties($create_task); 50 47 51 - $items[] = $this->newItem() 52 - ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_PROJECT) 53 - ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 54 - ->setMenuItemProperties($create_project); 48 + $items[] = $this->newItem() 49 + ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_PROJECT) 50 + ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 51 + ->setMenuItemProperties($create_project); 55 52 56 - $items[] = $this->newItem() 57 - ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_REPOSITORY) 58 - ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 59 - ->setMenuItemProperties($create_repository); 60 - } 53 + $items[] = $this->newItem() 54 + ->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_REPOSITORY) 55 + ->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY) 56 + ->setMenuItemProperties($create_repository); 61 57 62 58 return $items; 63 59 }
+85 -23
src/applications/search/engine/PhabricatorProfileMenuEngine.php
··· 6 6 private $profileObject; 7 7 private $customPHID; 8 8 private $items; 9 - private $menuType; 9 + private $menuType = self::MENU_GLOBAL; 10 10 private $defaultItem; 11 11 private $controller; 12 12 private $navigation; ··· 15 15 const MENU_GLOBAL = 'global'; 16 16 const MENU_PERSONAL = 'personal'; 17 17 const MENU_COMBINED = 'menu'; 18 + const ITEM_CUSTOM_DIVIDER = 'engine.divider'; 18 19 19 20 public function setViewer(PhabricatorUser $viewer) { 20 21 $this->viewer = $viewer; ··· 82 83 } 83 84 84 85 abstract protected function getItemURI($path); 86 + abstract protected function isMenuEngineConfigurable(); 85 87 86 - abstract protected function isMenuEngineConfigurable(); 88 + abstract protected function getBuiltinProfileItems($object); 89 + 90 + protected function getBuiltinCustomProfileItems( 91 + $object, 92 + $custom_phid) { 93 + return array(); 94 + } 87 95 88 96 public function buildResponse() { 89 97 $controller = $this->getController(); ··· 230 238 ->setBaseURI(new PhutilURI($this->getItemURI(''))); 231 239 232 240 $menu_items = $this->getItems(); 241 + 233 242 $filtered_items = array(); 234 243 foreach ($menu_items as $menu_item) { 235 244 if ($menu_item->isDisabled()) { ··· 294 303 $object = $this->getProfileObject(); 295 304 296 305 $items = $this->loadBuiltinProfileItems(); 297 - $menu = $this->getMenuType(); 298 306 299 - if ($this->getCustomPHID()) { 300 - $stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery()) 301 - ->setViewer($viewer) 302 - ->withProfilePHIDs(array($object->getPHID())) 303 - ->withCustomPHIDs(array($this->getCustomPHID())) 304 - ->setMenuType($menu) 305 - ->execute(); 306 - } else { 307 - $stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery()) 308 - ->setViewer($viewer) 309 - ->withProfilePHIDs(array($object->getPHID())) 310 - ->setMenuType($menu) 311 - ->execute(); 307 + $query = id(new PhabricatorProfileMenuItemConfigurationQuery()) 308 + ->setViewer($viewer) 309 + ->withProfilePHIDs(array($object->getPHID())); 310 + 311 + $menu_type = $this->getMenuType(); 312 + switch ($menu_type) { 313 + case self::MENU_GLOBAL: 314 + $query->withCustomPHIDs(array(), true); 315 + break; 316 + case self::MENU_PERSONAL: 317 + $query->withCustomPHIDs(array($this->getCustomPHID()), false); 318 + break; 319 + case self::MENU_COMBINED: 320 + $query->withCustomPHIDs(array($this->getCustomPHID()), true); 321 + break; 312 322 } 323 + 324 + $stored_items = $query->execute(); 313 325 314 326 foreach ($stored_items as $stored_item) { 315 327 $impl = $stored_item->getMenuItem(); ··· 339 351 } 340 352 } 341 353 342 - $items = msort($items, 'getSortKey'); 343 - 344 - // Normalize keys since callers shouldn't rely on this array being 345 - // partially keyed. 346 - $items = array_values($items); 347 - 354 + $items = $this->arrangeItems($items); 348 355 349 356 // Make sure exactly one valid item is marked as default. 350 357 $default = null; ··· 377 384 378 385 private function loadBuiltinProfileItems() { 379 386 $object = $this->getProfileObject(); 380 - $builtins = $this->getBuiltinProfileItems($object); 387 + 388 + $menu_type = $this->getMenuType(); 389 + switch ($menu_type) { 390 + case self::MENU_GLOBAL: 391 + $builtins = $this->getBuiltinProfileItems($object); 392 + break; 393 + case self::MENU_PERSONAL: 394 + $builtins = $this->getBuiltinCustomProfileItems( 395 + $object, 396 + $this->getCustomPHID()); 397 + break; 398 + case self::MENU_COMBINED: 399 + $builtins = array(); 400 + $builtins[] = $this->getBuiltinCustomProfileItems( 401 + $object, 402 + $this->getCustomPHID()); 403 + $builtins[] = $this->getBuiltinProfileItems($object); 404 + $builtins = array_mergev($builtins); 405 + break; 406 + } 381 407 382 408 $items = PhabricatorProfileMenuItem::getAllMenuItems(); 383 409 $viewer = $this->getViewer(); ··· 989 1015 990 1016 return $this; 991 1017 } 1018 + 1019 + private function arrangeItems(array $items) { 1020 + // Sort the items. 1021 + $items = msortv($items, 'getSortVector'); 1022 + 1023 + // If we have some global items and some custom items and are in "combined" 1024 + // mode, put a hard-coded divider item between them. 1025 + if ($this->getMenuType() == self::MENU_COMBINED) { 1026 + $list = array(); 1027 + $seen_custom = false; 1028 + $seen_global = false; 1029 + foreach ($items as $item) { 1030 + if ($item->getCustomPHID()) { 1031 + $seen_custom = true; 1032 + } else { 1033 + if ($seen_custom && !$seen_global) { 1034 + $list[] = $this->newItem() 1035 + ->setBuiltinKey(self::ITEM_CUSTOM_DIVIDER) 1036 + ->setMenuItemKey(PhabricatorDividerProfileMenuItem::MENUITEMKEY) 1037 + ->attachMenuItem( 1038 + new PhabricatorDividerProfileMenuItem()); 1039 + } 1040 + $seen_global = true; 1041 + } 1042 + $list[] = $item; 1043 + } 1044 + $items = $list; 1045 + } 1046 + 1047 + // Normalize keys since callers shouldn't rely on this array being 1048 + // partially keyed. 1049 + $items = array_values($items); 1050 + 1051 + return $items; 1052 + } 1053 + 992 1054 993 1055 }
+18 -11
src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php
··· 7 7 private $phids; 8 8 private $profilePHIDs; 9 9 private $customPHIDs; 10 - private $menuType; 10 + private $includeGlobal; 11 11 12 12 public function withIDs(array $ids) { 13 13 $this->ids = $ids; ··· 24 24 return $this; 25 25 } 26 26 27 - public function withCustomPHIDs(array $phids) { 27 + public function withCustomPHIDs(array $phids, $include_global = false) { 28 28 $this->customPHIDs = $phids; 29 - return $this; 30 - } 31 - 32 - public function setMenuType($type) { 33 - $this->menuType = $type; 29 + $this->includeGlobal = $include_global; 34 30 return $this; 35 31 } 36 32 ··· 67 63 } 68 64 69 65 if ($this->customPHIDs !== null) { 70 - $where[] = qsprintf( 71 - $conn, 72 - 'customPHID IN (%Ls)', 73 - $this->customPHIDs); 66 + if ($this->customPHIDs && $this->includeGlobal) { 67 + $where[] = qsprintf( 68 + $conn, 69 + 'customPHID IN (%Ls) OR customPHID IS NULL', 70 + $this->customPHIDs); 71 + } else if ($this->customPHIDs) { 72 + $where[] = qsprintf( 73 + $conn, 74 + 'customPHID IN (%Ls)', 75 + $this->customPHIDs); 76 + } else { 77 + $where[] = qsprintf( 78 + $conn, 79 + 'customPHID IS NULL'); 80 + } 74 81 } 75 82 76 83 return $where;
+18 -8
src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php
··· 126 126 return $this->getMenuItem()->willBuildNavigationItems($items); 127 127 } 128 128 129 - public function getSortKey() { 129 + public function getSortVector() { 130 + // Sort custom items above global items. 131 + if ($this->getCustomPHID()) { 132 + $is_global = 0; 133 + } else { 134 + $is_global = 1; 135 + } 136 + 137 + // Sort items with an explicit order above items without an explicit order, 138 + // so any newly created builtins go to the bottom. 130 139 $order = $this->getMenuItemOrder(); 131 - if ($order === null) { 132 - $order = 'Z'; 140 + if ($order !== null) { 141 + $has_order = 0; 133 142 } else { 134 - $order = sprintf('%020d', $order); 143 + $has_order = 1; 135 144 } 136 145 137 - return sprintf( 138 - '~%s%020d', 139 - $order, 140 - $this->getID()); 146 + return id(new PhutilSortVector()) 147 + ->addInt($is_global) 148 + ->addInt($has_order) 149 + ->addInt((int)$order) 150 + ->addInt((int)$this->getID()); 141 151 } 142 152 143 153 public function isDisabled() {