diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index b40b32e2a1..9e5aa560b7 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -90,6 +90,7 @@ phutil_register_library_map(array( 'AphrontUsageException' => 'aphront/exception/AphrontUsageException.php', 'AphrontView' => 'view/AphrontView.php', 'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', + 'AuditPeopleMenuEventListener' => 'applications/audit/events/AuditPeopleMenuEventListener.php', 'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php', 'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php', 'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php', @@ -206,6 +207,7 @@ phutil_register_library_map(array( 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php', 'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php', + 'ConpherencePeopleMenuEventListener' => 'applications/conpherence/events/ConpherencePeopleMenuEventListener.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', @@ -309,6 +311,7 @@ phutil_register_library_map(array( 'DifferentialNewDiffMail' => 'applications/differential/mail/DifferentialNewDiffMail.php', 'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php', 'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/DifferentialPathFieldSpecification.php', + 'DifferentialPeopleMenuEventListener' => 'applications/differential/events/DifferentialPeopleMenuEventListener.php', 'DifferentialPrimaryPaneView' => 'applications/differential/view/DifferentialPrimaryPaneView.php', 'DifferentialReplyHandler' => 'applications/differential/DifferentialReplyHandler.php', 'DifferentialResultsTableView' => 'applications/differential/view/DifferentialResultsTableView.php', @@ -422,6 +425,7 @@ phutil_register_library_map(array( 'DiffusionPathQuery' => 'applications/diffusion/query/DiffusionPathQuery.php', 'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php', 'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php', + 'DiffusionPeopleMenuEventListener' => 'applications/diffusion/events/DiffusionPeopleMenuEventListener.php', 'DiffusionQuery' => 'applications/diffusion/query/DiffusionQuery.php', 'DiffusionRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php', 'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php', @@ -565,6 +569,7 @@ phutil_register_library_map(array( 'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/ManiphestDefaultTaskExtensions.php', 'ManiphestEdgeEventListener' => 'applications/maniphest/event/ManiphestEdgeEventListener.php', 'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php', + 'ManiphestPeopleMenuEventListener' => 'applications/maniphest/event/ManiphestPeopleMenuEventListener.php', 'ManiphestReplyHandler' => 'applications/maniphest/ManiphestReplyHandler.php', 'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', 'ManiphestSavedQuery' => 'applications/maniphest/storage/ManiphestSavedQuery.php', @@ -1576,6 +1581,7 @@ phutil_register_library_map(array( 'AphrontUsageException' => 'AphrontException', 'AphrontView' => 'Phobject', 'AphrontWebpageResponse' => 'AphrontHTMLResponse', + 'AuditPeopleMenuEventListener' => 'PhutilEventListener', 'CelerityPhabricatorResourceController' => 'CelerityResourceController', 'CelerityResourceController' => 'PhabricatorController', 'CelerityResourceGraph' => 'AbstractDirectedGraph', @@ -1682,6 +1688,7 @@ phutil_register_library_map(array( 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipationStatus' => 'ConpherenceConstants', + 'ConpherencePeopleMenuEventListener' => 'PhutilEventListener', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', 'ConpherenceThread' => array( @@ -1781,6 +1788,7 @@ phutil_register_library_map(array( 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification', + 'DifferentialPeopleMenuEventListener' => 'PhutilEventListener', 'DifferentialPrimaryPaneView' => 'AphrontView', 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', 'DifferentialResultsTableView' => 'AphrontView', @@ -1876,6 +1884,7 @@ phutil_register_library_map(array( 'DiffusionPathCompleteController' => 'DiffusionController', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathValidateController' => 'DiffusionController', + 'DiffusionPeopleMenuEventListener' => 'PhutilEventListener', 'DiffusionRawDiffQuery' => 'DiffusionQuery', 'DiffusionRepositoryController' => 'DiffusionController', 'DiffusionSetupException' => 'AphrontUsageException', @@ -1988,6 +1997,7 @@ phutil_register_library_map(array( 'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions', 'ManiphestEdgeEventListener' => 'PhutilEventListener', 'ManiphestExportController' => 'ManiphestController', + 'ManiphestPeopleMenuEventListener' => 'PhutilEventListener', 'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler', 'ManiphestReportController' => 'ManiphestController', 'ManiphestSavedQuery' => 'ManiphestDAO', diff --git a/src/applications/audit/application/PhabricatorApplicationAudit.php b/src/applications/audit/application/PhabricatorApplicationAudit.php index d24e3a71a0..73ad9a2be3 100644 --- a/src/applications/audit/application/PhabricatorApplicationAudit.php +++ b/src/applications/audit/application/PhabricatorApplicationAudit.php @@ -18,6 +18,12 @@ final class PhabricatorApplicationAudit extends PhabricatorApplication { return PhabricatorEnv::getDoclink('article/Audit_User_Guide.html'); } + public function getEventListeners() { + return array( + new AuditPeopleMenuEventListener() + ); + } + public function getRoutes() { return array( '/audit/' => array( diff --git a/src/applications/audit/events/AuditPeopleMenuEventListener.php b/src/applications/audit/events/AuditPeopleMenuEventListener.php new file mode 100644 index 0000000000..3ab4b7739f --- /dev/null +++ b/src/applications/audit/events/AuditPeopleMenuEventListener.php @@ -0,0 +1,38 @@ +listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU: + $this->handleMenuEvent($event); + break; + } + } + + private function handleMenuEvent($event) { + $viewer = $event->getUser(); + $menu = $event->getValue('menu'); + $person = $event->getValue('person'); + $username = phutil_escape_uri($person->getUsername()); + + $href = '/audit/view/author/'.$username.'/'; + $name = pht('Commits'); + + $menu->addMenuItemToLabel('activity', + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setName($name) + ->setHref($href) + ->setKey($name) + ); + + $event->setValue('menu', $menu); + } + +} + diff --git a/src/applications/conpherence/application/PhabricatorApplicationConpherence.php b/src/applications/conpherence/application/PhabricatorApplicationConpherence.php index 71e7fb1b9f..9f78872453 100644 --- a/src/applications/conpherence/application/PhabricatorApplicationConpherence.php +++ b/src/applications/conpherence/application/PhabricatorApplicationConpherence.php @@ -33,6 +33,12 @@ final class PhabricatorApplicationConpherence extends PhabricatorApplication { return self::GROUP_COMMUNICATION; } + public function getEventListeners() { + return array( + new ConpherencePeopleMenuEventListener(), + ); + } + public function getRoutes() { return array( '/conpherence/' => array( diff --git a/src/applications/conpherence/events/ConpherencePeopleMenuEventListener.php b/src/applications/conpherence/events/ConpherencePeopleMenuEventListener.php new file mode 100644 index 0000000000..813763f9ae --- /dev/null +++ b/src/applications/conpherence/events/ConpherencePeopleMenuEventListener.php @@ -0,0 +1,38 @@ +listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU: + $this->handleMenuEvent($event); + break; + } + } + + private function handleMenuEvent($event) { + $viewer = $event->getUser(); + $menu = $event->getValue('menu'); + $person = $event->getValue('person'); + + $conpherence_uri = + new PhutilURI('/conpherence/new/?participant='.$person->getPHID()); + $name = pht('Conpherence'); + + $menu->addMenuItemBefore('activity', + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setName($name) + ->setHref($conpherence_uri) + ->setKey($name) + ); + + $event->setValue('menu', $menu); + } + +} + diff --git a/src/applications/differential/application/PhabricatorApplicationDifferential.php b/src/applications/differential/application/PhabricatorApplicationDifferential.php index baa795589a..a198b98d59 100644 --- a/src/applications/differential/application/PhabricatorApplicationDifferential.php +++ b/src/applications/differential/application/PhabricatorApplicationDifferential.php @@ -28,6 +28,12 @@ final class PhabricatorApplicationDifferential extends PhabricatorApplication { return "\xE2\x9A\x99"; } + public function getEventListeners() { + return array( + new DifferentialPeopleMenuEventListener() + ); + } + public function getRoutes() { return array( '/D(?P[1-9]\d*)' => 'DifferentialRevisionViewController', diff --git a/src/applications/differential/events/DifferentialPeopleMenuEventListener.php b/src/applications/differential/events/DifferentialPeopleMenuEventListener.php new file mode 100644 index 0000000000..59163ecdf3 --- /dev/null +++ b/src/applications/differential/events/DifferentialPeopleMenuEventListener.php @@ -0,0 +1,38 @@ +listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU: + $this->handleMenuEvent($event); + break; + } + } + + private function handleMenuEvent($event) { + $viewer = $event->getUser(); + $menu = $event->getValue('menu'); + $person = $event->getValue('person'); + $username = phutil_escape_uri($person->getUserName()); + + $href = '/differential/filter/revisions/'.$username.'/'; + $name = pht('Revisions'); + + $menu->addMenuItemToLabel('activity', + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setHref($href) + ->setName($name) + ->setKey($name) + ); + + $event->setValue('menu', $menu); + } + +} + diff --git a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php index 7eb4f27ccd..588c179d15 100644 --- a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php +++ b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php @@ -24,6 +24,12 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication { ); } + public function getEventListeners() { + return array( + new DiffusionPeopleMenuEventListener() + ); + } + public function getRoutes() { return array( '/r(?P[A-Z]+)(?P[a-z0-9]+)' diff --git a/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php b/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php new file mode 100644 index 0000000000..fc7e5a670d --- /dev/null +++ b/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php @@ -0,0 +1,37 @@ +listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU: + $this->handleMenuEvent($event); + break; + } + } + + private function handleMenuEvent($event) { + $viewer = $event->getUser(); + $menu = $event->getValue('menu'); + $person_phid = $event->getValue('person')->getPHID(); + + $href = '/diffusion/lint/?owner[0]='.$person_phid; + $name = pht('Lint Messages'); + + $menu->addMenuItemToLabel('activity', + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setHref($href) + ->setName($name) + ->setKey($name) + ); + + $event->setValue('menu', $menu); + } + +} + diff --git a/src/applications/maniphest/application/PhabricatorApplicationManiphest.php b/src/applications/maniphest/application/PhabricatorApplicationManiphest.php index 787c5eb6f7..654d99f341 100644 --- a/src/applications/maniphest/application/PhabricatorApplicationManiphest.php +++ b/src/applications/maniphest/application/PhabricatorApplicationManiphest.php @@ -36,6 +36,12 @@ final class PhabricatorApplicationManiphest extends PhabricatorApplication { return $this->getBaseURI().'task/create/'; } + public function getEventListeners() { + return array( + new ManiphestPeopleMenuEventListener() + ); + } + public function getRoutes() { return array( '/T(?P[1-9]\d*)' => 'ManiphestTaskDetailController', diff --git a/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php b/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php new file mode 100644 index 0000000000..99f0f8283b --- /dev/null +++ b/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php @@ -0,0 +1,36 @@ +listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU: + $this->handleMenuEvent($event); + break; + } + } + + private function handleMenuEvent($event) { + $viewer = $event->getUser(); + $menu = $event->getValue('menu'); + $person_phid = $event->getValue('person')->getPHID(); + + $href = '/maniphest/view/action/?persons='.$person_phid; + $name = pht('Tasks'); + + $menu->addMenuItemToLabel('activity', + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setHref($href) + ->setName($name) + ->setKey($name) + ); + + $event->setValue('menu', $menu); + } + +} diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 88a62a3dab..04cd8ec338 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -16,6 +16,21 @@ final class PhabricatorPeopleProfileController return $this->profileUser; } + private function getMainFilters($username) { + return array( + array( + 'key' => 'feed', + 'name' => pht('Feed'), + 'href' => '/p/'.$username.'/feed/' + ), + array( + 'key' => 'about', + 'name' => pht('About'), + 'href' => '/p/'.$username.'/about/' + ) + ); + } + public function processRequest() { $viewer = $this->getRequest()->getUser(); @@ -39,40 +54,14 @@ final class PhabricatorPeopleProfileController } $username = phutil_escape_uri($user->getUserName()); - $external_arrow = "\xE2\x86\x97"; + $menu = new PhabricatorMenuView(); + foreach ($this->getMainFilters($username) as $filter) { + $menu->newLink($filter['name'], $filter['href'], $filter['key']); + } - $conpherence_uri = - new PhutilURI('/conpherence/new/?participant='.$user->getPHID()); - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI('/p/'.$username.'/')); - $nav->addFilter('feed', 'Feed'); - $nav->addMenuItem( - id(new PhabricatorMenuItemView()) - ->setName(pht('Conpherence').' '.$external_arrow) - ->setHref($conpherence_uri) - ); - $nav->addFilter('about', 'About'); - $nav->addLabel('Activity'); - - $nav->addFilter( - null, - "Revisions {$external_arrow}", - '/differential/filter/revisions/'.$username.'/'); - - $nav->addFilter( - null, - "Tasks {$external_arrow}", - '/maniphest/view/action/?users='.$user->getPHID()); - - $nav->addFilter( - null, - "Commits {$external_arrow}", - '/audit/view/author/'.$username.'/'); - - $nav->addFilter( - null, - "Lint Messages {$external_arrow}", - '/diffusion/lint/?owner[0]='.$user->getPHID()); + $menu->newLabel(pht('Activity'), 'activity'); + // NOTE: applications install the various links through PhabricatorEvent + // listeners $oauths = id(new PhabricatorUserOAuthInfo())->loadAllWhere( 'userID = %d', @@ -92,18 +81,34 @@ final class PhabricatorPeopleProfileController continue; } - $name = $provider->getProviderName().' Profile'; + $name = pht('%s Profile', $provider->getProviderName()); $href = $oauths[$provider_key]->getAccountURI(); if ($href) { if (!$added_label) { - $nav->addLabel('Linked Accounts'); + $menu->newLabel(pht('Linked Accounts'), 'linked_accounts'); $added_label = true; } - $nav->addFilter(null, $name.' '.$external_arrow, $href); + $menu->addMenuItem( + id(new PhabricatorMenuItemView()) + ->setIsExternal(true) + ->setName($name) + ->setHref($href) + ->setType(PhabricatorMenuItemView::TYPE_LINK) + ); } } + $event = new PhabricatorEvent( + PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU, + array( + 'menu' => $menu, + 'person' => $user, + )); + $event->setUser($viewer); + PhutilEventEngine::dispatchEvent($event); + $nav = AphrontSideNavFilterView::newFromMenu($event->getValue('menu')); + $this->page = $nav->selectFilter($this->page, 'feed'); switch ($this->page) { @@ -141,14 +146,19 @@ final class PhabricatorPeopleProfileController $header->appendChild($content); if ($user->getPHID() == $viewer->getPHID()) { - $nav->addFilter(null, 'Edit Profile...', '/settings/panel/profile/'); + $nav->addFilter( + null, + pht('Edit Profile...'), + '/settings/panel/profile/' + ); } if ($viewer->getIsAdmin()) { $nav->addFilter( null, - 'Administrate User...', - '/people/edit/'.$user->getID().'/'); + pht('Administrate User...'), + '/people/edit/'.$user->getID().'/' + ); } return $this->buildApplicationPage( @@ -162,7 +172,10 @@ final class PhabricatorPeopleProfileController $blurb = nonempty( $profile->getBlurb(), - '//Nothing is known about this rare specimen.//'); + '//'. + pht('Nothing is known about this rare specimen.') + .'//' + ); $engine = PhabricatorMarkupEngine::newProfileMarkupEngine(); $blurb = $engine->markupText($blurb); diff --git a/src/infrastructure/events/constant/PhabricatorEventType.php b/src/infrastructure/events/constant/PhabricatorEventType.php index 39772ea4e4..f6f91e9e82 100644 --- a/src/infrastructure/events/constant/PhabricatorEventType.php +++ b/src/infrastructure/events/constant/PhabricatorEventType.php @@ -30,4 +30,5 @@ final class PhabricatorEventType extends PhutilEventType { const TYPE_UI_DDIDRENDEROBJECT = 'ui.didRenderObject'; const TYPE_UI_DIDRENDEROBJECTS = 'ui.didRenderObjects'; + const TYPE_PEOPLE_DIDRENDERMENU = 'people.didRenderMenu'; } diff --git a/src/view/layout/PhabricatorMenuView.php b/src/view/layout/PhabricatorMenuView.php index bf1d601eb2..c430fe76fd 100644 --- a/src/view/layout/PhabricatorMenuView.php +++ b/src/view/layout/PhabricatorMenuView.php @@ -8,21 +8,23 @@ final class PhabricatorMenuView extends AphrontTagView { return false; } - public function newLabel($name) { + public function newLabel($name, $key = null) { $item = id(new PhabricatorMenuItemView()) ->setType(PhabricatorMenuItemView::TYPE_LABEL) - ->setName($name); + ->setName($name) + ->setKey($key); $this->addMenuItem($item); return $item; } - public function newLink($name, $href) { + public function newLink($name, $href, $key = null) { $item = id(new PhabricatorMenuItemView()) ->setType(PhabricatorMenuItemView::TYPE_LINK) ->setName($name) - ->setHref($href); + ->setHref($href) + ->setKey($key); $this->addMenuItem($item);