Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php b/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php
index 3c86d19a58..87b59e3e0f 100644
--- a/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php
+++ b/src/applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php
@@ -1,48 +1,48 @@
<?php
final class PhabricatorFavoritesProfileMenuEngine
extends PhabricatorProfileMenuEngine {
protected function isMenuEngineConfigurable() {
return true;
}
- protected function getItemURI($path) {
+ public function getItemURI($path) {
$object = $this->getProfileObject();
$custom = $this->getCustomPHID();
if ($custom) {
return "/favorites/personal/item/{$path}";
} else {
return "/favorites/global/item/{$path}";
}
}
protected function getBuiltinProfileItems($object) {
$items = array();
$viewer = $this->getViewer();
$engines = PhabricatorEditEngine::getAllEditEngines();
$engines = msortv($engines, 'getQuickCreateOrderVector');
foreach ($engines as $engine) {
foreach ($engine->getDefaultQuickCreateFormKeys() as $form_key) {
$form_hash = PhabricatorHash::digestForIndex($form_key);
$builtin_key = "editengine.form({$form_hash})";
$properties = array(
'name' => null,
'formKey' => $form_key,
);
$items[] = $this->newItem()
->setBuiltinKey($builtin_key)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($properties);
}
}
return $items;
}
}
diff --git a/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php b/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php
index ebcc92b189..528edba697 100644
--- a/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php
+++ b/src/applications/home/engine/PhabricatorHomeProfileMenuEngine.php
@@ -1,58 +1,58 @@
<?php
final class PhabricatorHomeProfileMenuEngine
extends PhabricatorProfileMenuEngine {
protected function isMenuEngineConfigurable() {
return true;
}
- protected function getItemURI($path) {
+ public function getItemURI($path) {
$object = $this->getProfileObject();
$custom = $this->getCustomPHID();
if ($custom) {
return "/home/menu/personal/item/{$path}";
} else {
return "/home/menu/global/item/{$path}";
}
}
protected function getBuiltinProfileItems($object) {
$viewer = $this->getViewer();
$items = array();
$custom_phid = $this->getCustomPHID();
$applications = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withInstalled(true)
->withUnlisted(false)
->withLaunchable(true)
->execute();
foreach ($applications as $application) {
if (!$application->isPinnedByDefault($viewer)) {
continue;
}
$properties = array(
'name' => $application->getName(),
'application' => $application->getPHID(),
);
$items[] = $this->newItem()
->setBuiltinKey($application->getPHID())
->setMenuItemKey(PhabricatorApplicationProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($properties);
}
// Single Manage Item, switches URI based on admin/user
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorHomeConstants::ITEM_MANAGE)
->setMenuItemKey(
PhabricatorHomeManageProfileMenuItem::MENUITEMKEY);
return $items;
}
}
diff --git a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php
index 9965147a12..3d67872772 100644
--- a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php
+++ b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php
@@ -1,84 +1,84 @@
<?php
final class PhabricatorPeopleProfileMenuEngine
extends PhabricatorProfileMenuEngine {
const ITEM_PROFILE = 'people.profile';
const ITEM_MANAGE = 'people.manage';
protected function isMenuEngineConfigurable() {
return false;
}
- protected function getItemURI($path) {
+ public function getItemURI($path) {
$user = $this->getProfileObject();
$username = $user->getUsername();
$username = phutil_escape_uri($username);
return "/p/{$username}/item/{$path}";
}
protected function getBuiltinProfileItems($object) {
$viewer = $this->getViewer();
$items = array();
$items[] = $this->newItem()
->setBuiltinKey(self::ITEM_PROFILE)
->setMenuItemKey(PhabricatorPeopleDetailsProfileMenuItem::MENUITEMKEY);
$have_maniphest = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorManiphestApplication',
$viewer);
if ($have_maniphest) {
$uri = urisprintf(
'/maniphest/?statuses=open()&assigned=%s#R',
$object->getPHID());
$items[] = $this->newItem()
->setBuiltinKey('tasks')
->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY)
->setMenuItemProperty('icon', 'maniphest')
->setMenuItemProperty('name', pht('Open Tasks'))
->setMenuItemProperty('uri', $uri);
}
$have_differential = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorDifferentialApplication',
$viewer);
if ($have_differential) {
$uri = urisprintf(
'/differential/?authors=%s#R',
$object->getPHID());
$items[] = $this->newItem()
->setBuiltinKey('revisions')
->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY)
->setMenuItemProperty('icon', 'differential')
->setMenuItemProperty('name', pht('Revisions'))
->setMenuItemProperty('uri', $uri);
}
$have_diffusion = PhabricatorApplication::isClassInstalledForViewer(
'PhabricatorDiffusionApplication',
$viewer);
if ($have_diffusion) {
$uri = urisprintf(
'/diffusion/commit/?authors=%s#R',
$object->getPHID());
$items[] = $this->newItem()
->setBuiltinKey('commits')
->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY)
->setMenuItemProperty('icon', 'diffusion')
->setMenuItemProperty('name', pht('Commits'))
->setMenuItemProperty('uri', $uri);
}
$items[] = $this->newItem()
->setBuiltinKey(self::ITEM_MANAGE)
->setMenuItemKey(PhabricatorPeopleManageProfileMenuItem::MENUITEMKEY);
return $items;
}
}
diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php
index d2f8d4f58d..7d5dc37e0b 100644
--- a/src/applications/project/controller/PhabricatorProjectViewController.php
+++ b/src/applications/project/controller/PhabricatorProjectViewController.php
@@ -1,36 +1,37 @@
<?php
final class PhabricatorProjectViewController
extends PhabricatorProjectController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$request = $this->getRequest();
$viewer = $request->getViewer();
$response = $this->loadProject();
if ($response) {
return $response;
}
$project = $this->getProject();
$engine = $this->getProfileMenuEngine();
$default = $engine->getDefaultItem();
switch ($default->getBuiltinKey()) {
case PhabricatorProject::ITEM_WORKBOARD:
$controller_object = new PhabricatorProjectBoardViewController();
break;
case PhabricatorProject::ITEM_PROFILE:
- default:
$controller_object = new PhabricatorProjectProfileController();
break;
+ default:
+ return $engine->buildResponse();
}
return $this->delegateToController($controller_object);
}
}
diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php
index d3ea39e1e2..a39e7a8236 100644
--- a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php
+++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php
@@ -1,47 +1,47 @@
<?php
final class PhabricatorProjectProfileMenuEngine
extends PhabricatorProfileMenuEngine {
protected function isMenuEngineConfigurable() {
return true;
}
- protected function getItemURI($path) {
+ public function getItemURI($path) {
$project = $this->getProfileObject();
$id = $project->getID();
return "/project/{$id}/item/{$path}";
}
protected function getBuiltinProfileItems($object) {
$items = array();
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_PROFILE)
->setMenuItemKey(PhabricatorProjectDetailsProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_POINTS)
->setMenuItemKey(PhabricatorProjectPointsProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_WORKBOARD)
->setMenuItemKey(PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_MEMBERS)
->setMenuItemKey(PhabricatorProjectMembersProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_SUBPROJECTS)
->setMenuItemKey(
PhabricatorProjectSubprojectsProfileMenuItem::MENUITEMKEY);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorProject::ITEM_MANAGE)
->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY);
return $items;
}
}
diff --git a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php
index 1bd7e796dc..ddb59ec095 100644
--- a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php
+++ b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php
@@ -1,69 +1,64 @@
<?php
final class PhabricatorProjectManageProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'project.manage';
public function getMenuItemTypeName() {
return pht('Manage Project');
}
private function getDefaultName() {
return pht('Manage');
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
- public function canMakeDefault(
- PhabricatorProfileMenuItemConfiguration $config) {
- return true;
- }
-
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name');
if (strlen($name)) {
return $name;
}
return $this->getDefaultName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setPlaceholder($this->getDefaultName())
->setValue($config->getMenuItemProperty('name')),
);
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$project = $config->getProfileObject();
$id = $project->getID();
$name = $this->getDisplayName($config);
$icon = 'fa-gears';
$href = "/project/manage/{$id}/";
$item = $this->newItem()
->setHref($href)
->setName($name)
->setIcon($icon);
return array(
$item,
);
}
}
diff --git a/src/applications/search/engine/PhabricatorProfileMenuEngine.php b/src/applications/search/engine/PhabricatorProfileMenuEngine.php
index 3e11436ced..a6db1b2d2b 100644
--- a/src/applications/search/engine/PhabricatorProfileMenuEngine.php
+++ b/src/applications/search/engine/PhabricatorProfileMenuEngine.php
@@ -1,1067 +1,1090 @@
<?php
abstract class PhabricatorProfileMenuEngine extends Phobject {
private $viewer;
private $profileObject;
private $customPHID;
private $items;
private $menuType = self::MENU_GLOBAL;
private $defaultItem;
private $controller;
private $navigation;
private $showNavigation = true;
const MENU_GLOBAL = 'global';
const MENU_PERSONAL = 'personal';
const MENU_COMBINED = 'menu';
const ITEM_CUSTOM_DIVIDER = 'engine.divider';
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->viewer;
}
public function setProfileObject($profile_object) {
$this->profileObject = $profile_object;
return $this;
}
public function getProfileObject() {
return $this->profileObject;
}
public function setCustomPHID($custom_phid) {
$this->customPHID = $custom_phid;
return $this;
}
public function getCustomPHID() {
return $this->customPHID;
}
public function setController(PhabricatorController $controller) {
$this->controller = $controller;
return $this;
}
public function getController() {
return $this->controller;
}
private function setDefaultItem(
PhabricatorProfileMenuItemConfiguration $default_item) {
$this->defaultItem = $default_item;
return $this;
}
public function getDefaultItem() {
$this->loadItems();
return $this->defaultItem;
}
public function setMenuType($type) {
$this->menuType = $type;
return $this;
}
private function getMenuType() {
return $this->menuType;
}
public function setShowNavigation($show) {
$this->showNavigation = $show;
return $this;
}
public function getShowNavigation() {
return $this->showNavigation;
}
- abstract protected function getItemURI($path);
+ abstract public function getItemURI($path);
abstract protected function isMenuEngineConfigurable();
abstract protected function getBuiltinProfileItems($object);
protected function getBuiltinCustomProfileItems(
$object,
$custom_phid) {
return array();
}
public function buildResponse() {
$controller = $this->getController();
$viewer = $controller->getViewer();
$this->setViewer($viewer);
$request = $controller->getRequest();
$item_action = $request->getURIData('itemAction');
+ if (!$item_action) {
+ $item_action = 'view';
+ }
// If the engine is not configurable, don't respond to any of the editing
// or configuration routes.
if (!$this->isMenuEngineConfigurable()) {
switch ($item_action) {
case 'view':
break;
default:
return new Aphront404Response();
}
}
$item_id = $request->getURIData('itemID');
$item_list = $this->getItems();
$selected_item = null;
if (strlen($item_id)) {
$item_id_int = (int)$item_id;
foreach ($item_list as $item) {
if ($item_id_int) {
if ((int)$item->getID() === $item_id_int) {
$selected_item = $item;
break;
}
}
$builtin_key = $item->getBuiltinKey();
if ($builtin_key === (string)$item_id) {
$selected_item = $item;
break;
}
}
}
+ if (!$selected_item) {
+ if ($item_action == 'view') {
+ $selected_item = $this->getDefaultItem();
+ }
+ }
+
switch ($item_action) {
case 'view':
case 'info':
case 'hide':
case 'default':
case 'builtin':
if (!$selected_item) {
return new Aphront404Response();
}
break;
case 'edit':
if (!$request->getURIData('id')) {
// If we continue along the "edit" pathway without an ID, we hit an
// unrelated exception because we can not build a new menu item out
// of thin air. For menus, new items are created via the "new"
// action. Just catch this case and 404 early since there's currently
// no clean way to make EditEngine aware of this.
return new Aphront404Response();
}
break;
}
$navigation = $this->buildNavigation();
- $navigation->selectFilter('item.configure');
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
- switch ($this->getMenuType()) {
- case 'personal':
- $crumbs->addTextCrumb(pht('Personal'));
- break;
- case 'global':
- $crumbs->addTextCrumb(pht('Global'));
- break;
+
+ // TODO: This stuff might need a little tweaking at some point, since it
+ // causes "Global" and "Personal" to show up in contexts where they don't
+ // make sense, notably Projects.
+ if ($item_action != 'view') {
+ $navigation->selectFilter('item.configure');
+ switch ($this->getMenuType()) {
+ case 'personal':
+ $crumbs->addTextCrumb(pht('Personal'));
+ break;
+ case 'global':
+ $crumbs->addTextCrumb(pht('Global'));
+ break;
+ }
}
switch ($item_action) {
case 'view':
+ $navigation->selectFilter($selected_item->getItemIdentifier());
+
$content = $this->buildItemViewContent($selected_item);
+ $crumbs->addTextCrumb($selected_item->getDisplayName());
+ if (!$content) {
+ return new Aphront404Response();
+ }
break;
case 'configure':
$content = $this->buildItemConfigureContent($item_list);
$crumbs->addTextCrumb(pht('Configure Menu'));
break;
case 'reorder':
$content = $this->buildItemReorderContent($item_list);
break;
case 'new':
$item_key = $request->getURIData('itemKey');
$content = $this->buildItemNewContent($item_key);
break;
case 'builtin':
$content = $this->buildItemBuiltinContent($selected_item);
break;
case 'hide':
$content = $this->buildItemHideContent($selected_item);
break;
case 'default':
$content = $this->buildItemDefaultContent(
$selected_item,
$item_list);
break;
case 'edit':
$content = $this->buildItemEditContent();
break;
default:
throw new Exception(
pht(
'Unsupported item action "%s".',
$item_action));
}
if ($content instanceof AphrontResponse) {
return $content;
}
if ($content instanceof AphrontResponseProducerInterface) {
return $content;
}
$crumbs->setBorder(true);
$page = $controller->newPage()
->setTitle(pht('Configure Menu'))
->setCrumbs($crumbs)
->appendChild($content);
if ($this->getShowNavigation()) {
$page->setNavigation($navigation);
}
+
return $page;
}
public function buildNavigation() {
if ($this->navigation) {
return $this->navigation;
}
$nav = id(new AphrontSideNavFilterView())
->setIsProfileMenu(true)
->setBaseURI(new PhutilURI($this->getItemURI('')));
$menu_items = $this->getItems();
$filtered_items = array();
foreach ($menu_items as $menu_item) {
if ($menu_item->isDisabled()) {
continue;
}
$filtered_items[] = $menu_item;
}
$filtered_groups = mgroup($filtered_items, 'getMenuItemKey');
foreach ($filtered_groups as $group) {
$first_item = head($group);
$first_item->willBuildNavigationItems($group);
}
foreach ($menu_items as $menu_item) {
if ($menu_item->isDisabled()) {
continue;
}
$items = $menu_item->buildNavigationMenuItems();
foreach ($items as $item) {
$this->validateNavigationMenuItem($item);
}
// If the item produced only a single item which does not otherwise
// have a key, try to automatically assign it a reasonable key. This
// makes selecting the correct item simpler.
if (count($items) == 1) {
$item = head($items);
if ($item->getKey() === null) {
- $builtin_key = $menu_item->getBuiltinKey();
- $item_phid = $menu_item->getPHID();
- if ($builtin_key !== null) {
- $item->setKey($builtin_key);
- } else if ($item_phid !== null) {
- $item->setKey($item_phid);
- }
+ $item_identifier = $menu_item->getItemIdentifier();
+ $item->setKey($item_identifier);
}
}
foreach ($items as $item) {
$nav->addMenuItem($item);
}
}
$nav->selectFilter(null);
$this->navigation = $nav;
return $this->navigation;
}
private function getItems() {
if ($this->items === null) {
$this->items = $this->loadItems();
}
return $this->items;
}
private function loadItems() {
$viewer = $this->getViewer();
$object = $this->getProfileObject();
$items = $this->loadBuiltinProfileItems();
$query = id(new PhabricatorProfileMenuItemConfigurationQuery())
->setViewer($viewer)
->withProfilePHIDs(array($object->getPHID()));
$menu_type = $this->getMenuType();
switch ($menu_type) {
case self::MENU_GLOBAL:
$query->withCustomPHIDs(array(), true);
break;
case self::MENU_PERSONAL:
$query->withCustomPHIDs(array($this->getCustomPHID()), false);
break;
case self::MENU_COMBINED:
$query->withCustomPHIDs(array($this->getCustomPHID()), true);
break;
}
$stored_items = $query->execute();
foreach ($stored_items as $stored_item) {
$impl = $stored_item->getMenuItem();
$impl->setViewer($viewer);
+ $impl->setEngine($this);
}
// Merge the stored items into the builtin items. If a builtin item has
// a stored version, replace the defaults with the stored changes.
foreach ($stored_items as $stored_item) {
if (!$stored_item->shouldEnableForObject($object)) {
continue;
}
$builtin_key = $stored_item->getBuiltinKey();
if ($builtin_key !== null) {
// If this builtin actually exists, replace the builtin with the
// stored configuration. Otherwise, we're just going to drop the
// stored config: it corresponds to an out-of-date or uninstalled
// item.
if (isset($items[$builtin_key])) {
$items[$builtin_key] = $stored_item;
} else {
continue;
}
} else {
$items[] = $stored_item;
}
}
$items = $this->arrangeItems($items);
// Make sure exactly one valid item is marked as default.
$default = null;
$first = null;
foreach ($items as $item) {
if (!$item->canMakeDefault()) {
continue;
}
if ($item->isDefault()) {
$default = $item;
break;
}
if ($first === null) {
$first = $item;
}
}
if (!$default) {
$default = $first;
}
if ($default) {
$this->setDefaultItem($default);
}
return $items;
}
private function loadBuiltinProfileItems() {
$object = $this->getProfileObject();
$menu_type = $this->getMenuType();
switch ($menu_type) {
case self::MENU_GLOBAL:
$builtins = $this->getBuiltinProfileItems($object);
break;
case self::MENU_PERSONAL:
$builtins = $this->getBuiltinCustomProfileItems(
$object,
$this->getCustomPHID());
break;
case self::MENU_COMBINED:
$builtins = array();
$builtins[] = $this->getBuiltinCustomProfileItems(
$object,
$this->getCustomPHID());
$builtins[] = $this->getBuiltinProfileItems($object);
$builtins = array_mergev($builtins);
break;
}
$items = PhabricatorProfileMenuItem::getAllMenuItems();
$viewer = $this->getViewer();
$order = 1;
$map = array();
foreach ($builtins as $builtin) {
$builtin_key = $builtin->getBuiltinKey();
if (!$builtin_key) {
throw new Exception(
pht(
'Object produced a builtin item with no builtin item key! '.
'Builtin items must have a unique key.'));
}
if (isset($map[$builtin_key])) {
throw new Exception(
pht(
'Object produced two items with the same builtin key ("%s"). '.
'Each item must have a unique builtin key.',
$builtin_key));
}
$item_key = $builtin->getMenuItemKey();
$item = idx($items, $item_key);
if (!$item) {
throw new Exception(
pht(
'Builtin item ("%s") specifies a bad item key ("%s"); there '.
'is no corresponding item implementation available.',
$builtin_key,
$item_key));
}
$item = clone $item;
$item->setViewer($viewer);
+ $item->setEngine($this);
$builtin
->setProfilePHID($object->getPHID())
->attachMenuItem($item)
->attachProfileObject($object)
->setMenuItemOrder($order);
if (!$builtin->shouldEnableForObject($object)) {
continue;
}
$map[$builtin_key] = $builtin;
$order++;
}
return $map;
}
private function validateNavigationMenuItem($item) {
if (!($item instanceof PHUIListItemView)) {
throw new Exception(
pht(
'Expected buildNavigationMenuItems() to return a list of '.
'PHUIListItemView objects, but got a surprise.'));
}
}
public function getConfigureURI() {
return $this->getItemURI('configure/');
}
private function buildItemReorderContent(array $items) {
$viewer = $this->getViewer();
$object = $this->getProfileObject();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$object,
PhabricatorPolicyCapability::CAN_EDIT);
$controller = $this->getController();
$request = $controller->getRequest();
$request->validateCSRF();
$order = $request->getStrList('order');
$by_builtin = array();
$by_id = array();
foreach ($items as $key => $item) {
$id = $item->getID();
if ($id) {
$by_id[$id] = $key;
continue;
}
$builtin_key = $item->getBuiltinKey();
if ($builtin_key) {
$by_builtin[$builtin_key] = $key;
continue;
}
}
$key_order = array();
foreach ($order as $order_item) {
if (isset($by_id[$order_item])) {
$key_order[] = $by_id[$order_item];
continue;
}
if (isset($by_builtin[$order_item])) {
$key_order[] = $by_builtin[$order_item];
continue;
}
}
$items = array_select_keys($items, $key_order) + $items;
$type_order =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER;
$order = 1;
foreach ($items as $item) {
$xactions = array();
$xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction())
->setTransactionType($type_order)
->setNewValue($order);
$editor = id(new PhabricatorProfileMenuEditor())
->setContentSourceFromRequest($request)
->setActor($viewer)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($item, $xactions);
$order++;
}
return id(new AphrontRedirectResponse())
->setURI($this->getConfigureURI());
}
+ private function buildItemViewContent(
+ PhabricatorProfileMenuItemConfiguration $item) {
+ return $item->newPageContent();
+ }
private function buildItemConfigureContent(array $items) {
$viewer = $this->getViewer();
$object = $this->getProfileObject();
$filtered_groups = mgroup($items, 'getMenuItemKey');
foreach ($filtered_groups as $group) {
$first_item = head($group);
$first_item->willBuildNavigationItems($group);
}
// Users only need to be able to edit the object which this menu appears
// on if they're editing global menu items. For example, users do not need
// to be able to edit the Favorites application to add new items to the
// Favorites menu.
if (!$this->getCustomPHID()) {
PhabricatorPolicyFilter::requireCapability(
$viewer,
$object,
PhabricatorPolicyCapability::CAN_EDIT);
}
$list_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'reorder-profile-menu-items',
array(
'listID' => $list_id,
'orderURI' => $this->getItemURI('reorder/'),
));
$list = id(new PHUIObjectItemListView())
->setID($list_id)
->setNoDataString(pht('This menu currently has no items.'));
foreach ($items as $item) {
$id = $item->getID();
$builtin_key = $item->getBuiltinKey();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$item,
PhabricatorPolicyCapability::CAN_EDIT);
$view = id(new PHUIObjectItemView());
$name = $item->getDisplayName();
$type = $item->getMenuItemTypeName();
if (!strlen(trim($name))) {
$name = pht('Untitled "%s" Item', $type);
}
$view->setHeader($name);
$view->addAttribute($type);
if ($can_edit) {
$view
->setGrippable(true)
->addSigil('profile-menu-item')
->setMetadata(
array(
'key' => nonempty($id, $builtin_key),
));
if ($id) {
$default_uri = $this->getItemURI("default/{$id}/");
} else {
$default_uri = $this->getItemURI("default/{$builtin_key}/");
}
if ($item->isDefault()) {
$default_icon = 'fa-thumb-tack green';
$default_text = pht('Current Default');
} else if ($item->canMakeDefault()) {
$default_icon = 'fa-thumb-tack';
$default_text = pht('Make Default');
} else {
$default_text = null;
}
if ($default_text !== null) {
$view->addAction(
id(new PHUIListItemView())
->setHref($default_uri)
->setWorkflow(true)
->setName($default_text)
->setIcon($default_icon));
}
if ($id) {
$view->setHref($this->getItemURI("edit/{$id}/"));
$hide_uri = $this->getItemURI("hide/{$id}/");
} else {
$view->setHref($this->getItemURI("builtin/{$builtin_key}/"));
$hide_uri = $this->getItemURI("hide/{$builtin_key}/");
}
if ($item->isDisabled()) {
$hide_icon = 'fa-plus';
$hide_text = pht('Enable');
} else if ($item->getBuiltinKey() !== null) {
$hide_icon = 'fa-times';
$hide_text = pht('Disable');
} else {
$hide_icon = 'fa-times';
$hide_text = pht('Delete');
}
$can_disable = $item->canHideMenuItem();
$view->addAction(
id(new PHUIListItemView())
->setHref($hide_uri)
->setWorkflow(true)
->setDisabled(!$can_disable)
->setName($hide_text)
->setIcon($hide_icon));
}
if ($item->isDisabled()) {
$view->setDisabled(true);
}
$list->addItem($view);
}
$action_view = id(new PhabricatorActionListView())
->setUser($viewer);
$item_types = PhabricatorProfileMenuItem::getAllMenuItems();
$object = $this->getProfileObject();
$action_list = id(new PhabricatorActionListView())
->setViewer($viewer);
$action_list->addAction(
id(new PhabricatorActionView())
->setLabel(true)
->setName(pht('Add New Menu Item...')));
foreach ($item_types as $item_type) {
if (!$item_type->canAddToObject($object)) {
continue;
}
$item_key = $item_type->getMenuItemKey();
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon($item_type->getMenuItemTypeIcon())
->setName($item_type->getMenuItemTypeName())
->setHref($this->getItemURI("new/{$item_key}/"))
->setWorkflow(true));
}
$action_list->addAction(
id(new PhabricatorActionView())
->setLabel(true)
->setName(pht('Documentation')));
$doc_link = PhabricatorEnv::getDoclink('Profile Menu User Guide');
$doc_name = pht('Profile Menu User Guide');
$action_list->addAction(
id(new PhabricatorActionView())
->setIcon('fa-book')
->setHref($doc_link)
->setName($doc_name));
$header = id(new PHUIHeaderView())
->setHeader(pht('Menu Items'))
->setHeaderIcon('fa-list');
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Current Menu Items'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
$panel = id(new PHUICurtainPanelView())
->appendChild($action_view);
$curtain = id(new PHUICurtainView())
->setViewer($viewer)
->setActionList($action_list);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(
array(
$box,
));
return $view;
}
private function buildItemNewContent($item_key) {
$item_types = PhabricatorProfileMenuItem::getAllMenuItems();
$item_type = idx($item_types, $item_key);
if (!$item_type) {
return new Aphront404Response();
}
$object = $this->getProfileObject();
if (!$item_type->canAddToObject($object)) {
return new Aphront404Response();
}
$custom_phid = $this->getCustomPHID();
$configuration = PhabricatorProfileMenuItemConfiguration::initializeNewItem(
$object,
$item_type,
$custom_phid);
$viewer = $this->getViewer();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$configuration,
PhabricatorPolicyCapability::CAN_EDIT);
$controller = $this->getController();
return id(new PhabricatorProfileMenuEditEngine())
->setMenuEngine($this)
->setProfileObject($object)
->setNewMenuItemConfiguration($configuration)
->setCustomPHID($custom_phid)
->setController($controller)
->buildResponse();
}
private function buildItemEditContent() {
$viewer = $this->getViewer();
$object = $this->getProfileObject();
$controller = $this->getController();
return id(new PhabricatorProfileMenuEditEngine())
->setMenuEngine($this)
->setProfileObject($object)
->setController($controller)
->setCustomPHID($this->getCustomPHID())
->buildResponse();
}
private function buildItemBuiltinContent(
PhabricatorProfileMenuItemConfiguration $configuration) {
// If this builtin item has already been persisted, redirect to the
// edit page.
$id = $configuration->getID();
if ($id) {
return id(new AphrontRedirectResponse())
->setURI($this->getItemURI("edit/{$id}/"));
}
// Otherwise, act like we're creating a new item, we're just starting
// with the builtin template.
$viewer = $this->getViewer();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$configuration,
PhabricatorPolicyCapability::CAN_EDIT);
$object = $this->getProfileObject();
$controller = $this->getController();
return id(new PhabricatorProfileMenuEditEngine())
->setIsBuiltin(true)
->setMenuEngine($this)
->setProfileObject($object)
->setNewMenuItemConfiguration($configuration)
->setController($controller)
->setCustomPHID($this->getCustomPHID())
->buildResponse();
}
private function buildItemHideContent(
PhabricatorProfileMenuItemConfiguration $configuration) {
$controller = $this->getController();
$request = $controller->getRequest();
$viewer = $this->getViewer();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$configuration,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$configuration->canHideMenuItem()) {
return $controller->newDialog()
->setTitle(pht('Mandatory Item'))
->appendParagraph(
pht('This menu item is very important, and can not be disabled.'))
->addCancelButton($this->getConfigureURI());
}
if ($configuration->getBuiltinKey() === null) {
$new_value = null;
$title = pht('Delete Menu Item');
$body = pht('Delete this menu item?');
$button = pht('Delete Menu Item');
} else if ($configuration->isDisabled()) {
$new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE;
$title = pht('Enable Menu Item');
$body = pht(
'Enable this menu item? It will appear in the menu again.');
$button = pht('Enable Menu Item');
} else {
$new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DISABLED;
$title = pht('Disable Menu Item');
$body = pht(
'Disable this menu item? It will no longer appear in the menu, but '.
'you can re-enable it later.');
$button = pht('Disable Menu Item');
}
$v_visibility = $configuration->getVisibility();
if ($request->isFormPost()) {
if ($new_value === null) {
$configuration->delete();
} else {
$type_visibility =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY;
$xactions = array();
$xactions[] =
id(new PhabricatorProfileMenuItemConfigurationTransaction())
->setTransactionType($type_visibility)
->setNewValue($new_value);
$editor = id(new PhabricatorProfileMenuEditor())
->setContentSourceFromRequest($request)
->setActor($viewer)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($configuration, $xactions);
}
return id(new AphrontRedirectResponse())
->setURI($this->getConfigureURI());
}
return $controller->newDialog()
->setTitle($title)
->appendParagraph($body)
->addCancelButton($this->getConfigureURI())
->addSubmitButton($button);
}
private function buildItemDefaultContent(
PhabricatorProfileMenuItemConfiguration $configuration,
array $items) {
$controller = $this->getController();
$request = $controller->getRequest();
$viewer = $this->getViewer();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$configuration,
PhabricatorPolicyCapability::CAN_EDIT);
$done_uri = $this->getConfigureURI();
if (!$configuration->canMakeDefault()) {
return $controller->newDialog()
->setTitle(pht('Not Defaultable'))
->appendParagraph(
pht(
'This item can not be set as the default item. This is usually '.
'because the item has no page of its own, or links to an '.
'external page.'))
->addCancelButton($done_uri);
}
if ($configuration->isDefault()) {
return $controller->newDialog()
->setTitle(pht('Already Default'))
->appendParagraph(
pht(
'This item is already set as the default item for this menu.'))
->addCancelButton($done_uri);
}
if ($request->isFormPost()) {
$key = $configuration->getID();
if (!$key) {
$key = $configuration->getBuiltinKey();
}
$this->adjustDefault($key);
return id(new AphrontRedirectResponse())
->setURI($done_uri);
}
return $controller->newDialog()
->setTitle(pht('Make Default'))
->appendParagraph(
pht(
'Set this item as the default for this menu? Users arriving on '.
'this page will be shown the content of this item by default.'))
->addCancelButton($done_uri)
->addSubmitButton(pht('Make Default'));
}
protected function newItem() {
return PhabricatorProfileMenuItemConfiguration::initializeNewBuiltin();
}
public function adjustDefault($key) {
$controller = $this->getController();
$request = $controller->getRequest();
$viewer = $request->getViewer();
$items = $this->loadItems();
// To adjust the default item, we first change any existing items that
// are marked as defaults to "visible", then make the new default item
// the default.
$default = array();
$visible = array();
foreach ($items as $item) {
$builtin_key = $item->getBuiltinKey();
$id = $item->getID();
$is_target =
(($builtin_key !== null) && ($builtin_key === $key)) ||
(($id !== null) && ((int)$id === (int)$key));
if ($is_target) {
if (!$item->isDefault()) {
$default[] = $item;
}
} else {
if ($item->isDefault()) {
$visible[] = $item;
}
}
}
$type_visibility =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY;
$v_visible = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE;
$v_default = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT;
$apply = array(
array($v_visible, $visible),
array($v_default, $default),
);
foreach ($apply as $group) {
list($value, $items) = $group;
foreach ($items as $item) {
$xactions = array();
$xactions[] =
id(new PhabricatorProfileMenuItemConfigurationTransaction())
->setTransactionType($type_visibility)
->setNewValue($value);
$editor = id(new PhabricatorProfileMenuEditor())
->setContentSourceFromRequest($request)
->setActor($viewer)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($item, $xactions);
}
}
return $this;
}
private function arrangeItems(array $items) {
// Sort the items.
$items = msortv($items, 'getSortVector');
// If we have some global items and some custom items and are in "combined"
// mode, put a hard-coded divider item between them.
if ($this->getMenuType() == self::MENU_COMBINED) {
$list = array();
$seen_custom = false;
$seen_global = false;
foreach ($items as $item) {
if ($item->getCustomPHID()) {
$seen_custom = true;
} else {
if ($seen_custom && !$seen_global) {
$list[] = $this->newItem()
->setBuiltinKey(self::ITEM_CUSTOM_DIVIDER)
->setMenuItemKey(PhabricatorDividerProfileMenuItem::MENUITEMKEY)
->attachMenuItem(
new PhabricatorDividerProfileMenuItem());
}
$seen_global = true;
}
$list[] = $item;
}
$items = $list;
}
// Normalize keys since callers shouldn't rely on this array being
// partially keyed.
$items = array_values($items);
return $items;
}
}
diff --git a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
index c9a13bd4ab..002e5778d5 100644
--- a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
+++ b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
@@ -1,160 +1,190 @@
<?php
final class PhabricatorDashboardProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'dashboard';
const FIELD_DASHBOARD = 'dashboardPHID';
private $dashboard;
public function getMenuItemTypeIcon() {
return 'fa-dashboard';
}
public function getMenuItemTypeName() {
return pht('Dashboard');
}
public function canAddToObject($object) {
return true;
}
+ public function canMakeDefault(
+ PhabricatorProfileMenuItemConfiguration $config) {
+ return true;
+ }
+
public function attachDashboard($dashboard) {
$this->dashboard = $dashboard;
return $this;
}
public function getDashboard() {
$dashboard = $this->dashboard;
+
if (!$dashboard) {
return null;
} else if ($dashboard->isArchived()) {
return null;
}
+
return $dashboard;
}
+ public function newPageContent(
+ PhabricatorProfileMenuItemConfiguration $config) {
+ $viewer = $this->getViewer();
+
+ $dashboard_phid = $config->getMenuItemProperty('dashboardPHID');
+
+ // Reload the dashboard to attach panels, which we need for rendering.
+ $dashboard = id(new PhabricatorDashboardQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($dashboard_phid))
+ ->needPanels(true)
+ ->executeOne();
+ if (!$dashboard) {
+ return null;
+ }
+
+ $engine = id(new PhabricatorDashboardRenderingEngine())
+ ->setViewer($viewer)
+ ->setDashboard($dashboard);
+
+ return $engine->renderDashboard();
+ }
+
public function willBuildNavigationItems(array $items) {
$viewer = $this->getViewer();
$dashboard_phids = array();
foreach ($items as $item) {
$dashboard_phids[] = $item->getMenuItemProperty('dashboardPHID');
}
$dashboards = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withPHIDs($dashboard_phids)
->execute();
$dashboards = mpull($dashboards, null, 'getPHID');
foreach ($items as $item) {
$dashboard_phid = $item->getMenuItemProperty('dashboardPHID');
$dashboard = idx($dashboards, $dashboard_phid, null);
$item->getMenuItem()->attachDashboard($dashboard);
}
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$dashboard = $this->getDashboard();
if (!$dashboard) {
return pht('(Restricted/Invalid Dashboard)');
}
if (strlen($this->getName($config))) {
return $this->getName($config);
} else {
return $dashboard->getName();
}
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorDatasourceEditField())
->setKey(self::FIELD_DASHBOARD)
->setLabel(pht('Dashboard'))
->setIsRequired(true)
->setDatasource(new PhabricatorDashboardDatasource())
->setSingleValue($config->getMenuItemProperty('dashboardPHID')),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setValue($this->getName($config)),
);
}
private function getName(
PhabricatorProfileMenuItemConfiguration $config) {
return $config->getMenuItemProperty('name');
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$dashboard = $this->getDashboard();
if (!$dashboard) {
return array();
}
$icon = $dashboard->getIcon();
$name = $this->getDisplayName($config);
- $href = $dashboard->getViewURI();
+ $href = $this->getItemViewURI($config);
$item = $this->newItem()
->setHref($href)
->setName($name)
->setIcon($icon);
return array(
$item,
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_DASHBOARD) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a dashboard.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
$dashboards = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withPHIDs(array($new))
->execute();
if (!$dashboards) {
$errors[] = $this->newInvalidError(
pht(
'Dashboard "%s" is not a valid dashboard which you have '.
'permission to see.',
$new),
$xaction['xaction']);
}
}
}
return $errors;
}
}
diff --git a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
index 6f1342d4c0..061afc7fad 100644
--- a/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
+++ b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php
@@ -1,110 +1,134 @@
<?php
abstract class PhabricatorProfileMenuItem extends Phobject {
private $viewer;
+ private $engine;
final public function buildNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
return $this->newNavigationMenuItems($config);
}
abstract protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config);
public function willBuildNavigationItems(array $items) {}
public function getMenuItemTypeIcon() {
return null;
}
abstract public function getMenuItemTypeName();
abstract public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config);
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array();
}
public function canAddToObject($object) {
return false;
}
public function shouldEnableForObject($object) {
return true;
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return true;
}
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->viewer;
}
+ public function setEngine(PhabricatorProfileMenuEngine $engine) {
+ $this->engine = $engine;
+ return $this;
+ }
+
+ public function getEngine() {
+ return $this->engine;
+ }
+
final public function getMenuItemKey() {
return $this->getPhobjectClassConstant('MENUITEMKEY');
}
final public static function getAllMenuItems() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getMenuItemKey')
->execute();
}
protected function newItem() {
return new PHUIListItemView();
}
+ public function newPageContent(
+ PhabricatorProfileMenuItemConfiguration $config) {
+ return null;
+ }
+
+ public function getItemViewURI(
+ PhabricatorProfileMenuItemConfiguration $config) {
+
+ $engine = $this->getEngine();
+ $key = $config->getItemIdentifier();
+
+ return $engine->getItemURI("view/{$key}/");
+ }
+
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
return array();
}
final protected function isEmptyTransaction($value, array $xactions) {
$result = $value;
foreach ($xactions as $xaction) {
$result = $xaction['new'];
}
return !strlen($result);
}
final protected function newError($title, $message, $xaction = null) {
return new PhabricatorApplicationTransactionValidationError(
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY,
$title,
$message,
$xaction);
}
final protected function newRequiredError($message, $type) {
$xaction = id(new PhabricatorProfileMenuItemConfigurationTransaction())
->setMetadataValue('property.key', $type);
return $this->newError(pht('Required'), $message, $xaction)
->setIsMissingFieldError(true);
}
final protected function newInvalidError($message, $xaction = null) {
return $this->newError(pht('Invalid'), $message, $xaction);
}
}
diff --git a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php
index 107fa63c72..f178cc49fe 100644
--- a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php
+++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php
@@ -1,262 +1,275 @@
<?php
final class PhabricatorProfileMenuItemConfiguration
extends PhabricatorSearchDAO
implements
PhabricatorPolicyInterface,
PhabricatorExtendedPolicyInterface,
PhabricatorApplicationTransactionInterface {
protected $profilePHID;
protected $menuItemKey;
protected $builtinKey;
protected $menuItemOrder;
protected $visibility;
protected $customPHID;
protected $menuItemProperties = array();
private $profileObject = self::ATTACHABLE;
private $menuItem = self::ATTACHABLE;
const VISIBILITY_DEFAULT = 'default';
const VISIBILITY_VISIBLE = 'visible';
const VISIBILITY_DISABLED = 'disabled';
public function getTableName() {
// For now, this class uses an older table name.
return 'search_profilepanelconfiguration';
}
public static function initializeNewBuiltin() {
return id(new self())
->setVisibility(self::VISIBILITY_VISIBLE);
}
public static function initializeNewItem(
$profile_object,
PhabricatorProfileMenuItem $item,
$custom_phid) {
return self::initializeNewBuiltin()
->setProfilePHID($profile_object->getPHID())
->setMenuItemKey($item->getMenuItemKey())
->attachMenuItem($item)
->attachProfileObject($profile_object)
->setCustomPHID($custom_phid);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'menuItemProperties' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'menuItemKey' => 'text64',
'builtinKey' => 'text64?',
'menuItemOrder' => 'uint32?',
'customPHID' => 'phid?',
'visibility' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_profile' => array(
'columns' => array('profilePHID', 'menuItemOrder'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorProfileMenuItemPHIDType::TYPECONST);
}
public function attachMenuItem(PhabricatorProfileMenuItem $item) {
$this->menuItem = $item;
return $this;
}
public function getMenuItem() {
return $this->assertAttached($this->menuItem);
}
public function attachProfileObject($profile_object) {
$this->profileObject = $profile_object;
return $this;
}
public function getProfileObject() {
return $this->assertAttached($this->profileObject);
}
public function setMenuItemProperty($key, $value) {
$this->menuItemProperties[$key] = $value;
return $this;
}
public function getMenuItemProperty($key, $default = null) {
return idx($this->menuItemProperties, $key, $default);
}
public function buildNavigationMenuItems() {
return $this->getMenuItem()->buildNavigationMenuItems($this);
}
public function getMenuItemTypeName() {
return $this->getMenuItem()->getMenuItemTypeName();
}
public function getDisplayName() {
return $this->getMenuItem()->getDisplayName($this);
}
public function canMakeDefault() {
return $this->getMenuItem()->canMakeDefault($this);
}
public function canHideMenuItem() {
return $this->getMenuItem()->canHideMenuItem($this);
}
public function shouldEnableForObject($object) {
return $this->getMenuItem()->shouldEnableForObject($object);
}
public function willBuildNavigationItems(array $items) {
return $this->getMenuItem()->willBuildNavigationItems($items);
}
public function validateTransactions(array $map) {
$item = $this->getMenuItem();
$fields = $item->buildEditEngineFields($this);
$errors = array();
foreach ($fields as $field) {
$field_key = $field->getKey();
$xactions = idx($map, $field_key, array());
$value = $this->getMenuItemProperty($field_key);
$field_errors = $item->validateTransactions(
$this,
$field_key,
$value,
$xactions);
foreach ($field_errors as $error) {
$errors[] = $error;
}
}
return $errors;
}
public function getSortVector() {
// Sort custom items above global items.
if ($this->getCustomPHID()) {
$is_global = 0;
} else {
$is_global = 1;
}
// Sort items with an explicit order above items without an explicit order,
// so any newly created builtins go to the bottom.
$order = $this->getMenuItemOrder();
if ($order !== null) {
$has_order = 0;
} else {
$has_order = 1;
}
return id(new PhutilSortVector())
->addInt($is_global)
->addInt($has_order)
->addInt((int)$order)
->addInt((int)$this->getID());
}
public function isDisabled() {
if (!$this->canHideMenuItem()) {
return false;
}
return ($this->getVisibility() === self::VISIBILITY_DISABLED);
}
public function isDefault() {
return ($this->getVisibility() === self::VISIBILITY_DEFAULT);
}
+ public function getItemIdentifier() {
+ $id = $this->getID();
+
+ if ($id) {
+ return (int)$id;
+ }
+
+ return $this->getBuiltinKey();
+ }
+
+ public function newPageContent() {
+ return $this->getMenuItem()->newPageContent($this);
+ }
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::getMostOpenPolicy();
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getProfileObject()->hasAutomaticCapability(
$capability,
$viewer);
}
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
// If this is an item with a custom PHID (like a personal menu item),
// we only require that the user can edit the corresponding custom
// object (usually their own user profile), not the object that the
// menu appears on (which may be an Application like Favorites or Home).
if ($capability == PhabricatorPolicyCapability::CAN_EDIT) {
if ($this->getCustomPHID()) {
return array(
array(
$this->getCustomPHID(),
$capability,
),
);
}
}
return array(
array(
$this->getProfileObject(),
$capability,
),
);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorProfileMenuEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new PhabricatorProfileMenuItemConfigurationTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 11:34 PM (23 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141342
Default Alt Text
(59 KB)

Event Timeline