From b83b3224bb756a2c2e29727df01b1c419f2c832b Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 1 Nov 2019 10:13:13 -0700 Subject: [PATCH] Add an "Advanced/Developer..." action item for viewing object handle details and hovercards Summary: Ref T13442. Ref T13157. There's a secret URI to look at an object's hovercard in a standalone view, but it's hard to remember and impossible to discover. In developer mode, add an action to "View Hovercard". Also add "View Handle", which primarily shows the object PHID. Test Plan: Viewed some objects, saw "Advanced/Developer...". Used "View Hovercard" to view hovercards and "View Handle" to view handles. Maniphest Tasks: T13442, T13157 Differential Revision: https://secure.phabricator.com/D20887 --- src/__phutil_library_map__.php | 4 + .../PhabricatorSearchApplication.php | 2 + .../PhabricatorSearchHandleController.php | 89 +++++++++++++++++++ .../PhabricatorSystemApplication.php | 6 ++ .../PhabricatorSystemDebugUIEventListener.php | 58 ++++++++++++ src/view/layout/PhabricatorActionListView.php | 8 ++ 6 files changed, 167 insertions(+) create mode 100644 src/applications/search/controller/PhabricatorSearchHandleController.php create mode 100644 src/applications/system/events/PhabricatorSystemDebugUIEventListener.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 2db41f0a69..bb6aeb20a1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4648,6 +4648,7 @@ phutil_register_library_map(array( 'PhabricatorSearchEngineExtensionModule' => 'applications/search/engineextension/PhabricatorSearchEngineExtensionModule.php', 'PhabricatorSearchFerretNgramGarbageCollector' => 'applications/search/garbagecollector/PhabricatorSearchFerretNgramGarbageCollector.php', 'PhabricatorSearchField' => 'applications/search/field/PhabricatorSearchField.php', + 'PhabricatorSearchHandleController' => 'applications/search/controller/PhabricatorSearchHandleController.php', 'PhabricatorSearchHost' => 'infrastructure/cluster/search/PhabricatorSearchHost.php', 'PhabricatorSearchHovercardController' => 'applications/search/controller/PhabricatorSearchHovercardController.php', 'PhabricatorSearchIndexVersion' => 'applications/search/storage/PhabricatorSearchIndexVersion.php', @@ -4872,6 +4873,7 @@ phutil_register_library_map(array( 'PhabricatorSystemActionRateLimitException' => 'applications/system/exception/PhabricatorSystemActionRateLimitException.php', 'PhabricatorSystemApplication' => 'applications/system/application/PhabricatorSystemApplication.php', 'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php', + 'PhabricatorSystemDebugUIEventListener' => 'applications/system/events/PhabricatorSystemDebugUIEventListener.php', 'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php', 'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php', 'PhabricatorSystemObjectController' => 'applications/system/controller/PhabricatorSystemObjectController.php', @@ -11270,6 +11272,7 @@ phutil_register_library_map(array( 'PhabricatorSearchEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorSearchFerretNgramGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorSearchField' => 'Phobject', + 'PhabricatorSearchHandleController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchHost' => 'Phobject', 'PhabricatorSearchHovercardController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchIndexVersion' => 'PhabricatorSearchDAO', @@ -11511,6 +11514,7 @@ phutil_register_library_map(array( 'PhabricatorSystemActionRateLimitException' => 'Exception', 'PhabricatorSystemApplication' => 'PhabricatorApplication', 'PhabricatorSystemDAO' => 'PhabricatorLiskDAO', + 'PhabricatorSystemDebugUIEventListener' => 'PhabricatorEventListener', 'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO', 'PhabricatorSystemObjectController' => 'PhabricatorController', diff --git a/src/applications/search/application/PhabricatorSearchApplication.php b/src/applications/search/application/PhabricatorSearchApplication.php index 3cf5923b9c..7547506258 100644 --- a/src/applications/search/application/PhabricatorSearchApplication.php +++ b/src/applications/search/application/PhabricatorSearchApplication.php @@ -33,6 +33,8 @@ final class PhabricatorSearchApplication extends PhabricatorApplication { 'index/(?P[^/]+)/' => 'PhabricatorSearchIndexController', 'hovercard/' => 'PhabricatorSearchHovercardController', + 'handle/(?P[^/]+)/' + => 'PhabricatorSearchHandleController', 'edit/' => array( 'key/(?P[^/]+)/' => 'PhabricatorSearchEditController', 'id/(?P[^/]+)/' => 'PhabricatorSearchEditController', diff --git a/src/applications/search/controller/PhabricatorSearchHandleController.php b/src/applications/search/controller/PhabricatorSearchHandleController.php new file mode 100644 index 0000000000..751b4e367d --- /dev/null +++ b/src/applications/search/controller/PhabricatorSearchHandleController.php @@ -0,0 +1,89 @@ +getViewer(); + $phid = $request->getURIData('phid'); + + $handles = $viewer->loadHandles(array($phid)); + $handle = $handles[$phid]; + + $cancel_uri = $handle->getURI(); + if (!$cancel_uri) { + $cancel_uri = '/'; + } + + $rows = array(); + + $rows[] = array( + pht('PHID'), + $phid, + ); + + $rows[] = array( + pht('PHID Type'), + phid_get_type($phid), + ); + + $rows[] = array( + pht('URI'), + $handle->getURI(), + ); + + $icon = $handle->getIcon(); + if ($icon !== null) { + $icon = id(new PHUIIconView()) + ->setIcon($handle->getIcon()); + } + + $rows[] = array( + pht('Icon'), + $icon, + ); + + $rows[] = array( + pht('Object Name'), + $handle->getObjectName(), + ); + + $rows[] = array( + pht('Name'), + $handle->getName(), + ); + + $rows[] = array( + pht('Full Name'), + $handle->getFullName(), + ); + + $rows[] = array( + pht('Tag'), + $handle->renderTag(), + ); + + $rows[] = array( + pht('Link'), + $handle->renderLink(), + ); + + $table = id(new AphrontTableView($rows)) + ->setColumnClasses( + array( + 'header', + 'wide', + )); + + return $this->newDialog() + ->setTitle(pht('Handle: %s', $phid)) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendChild($table) + ->addCancelButton($cancel_uri, pht('Done')); + } + +} diff --git a/src/applications/system/application/PhabricatorSystemApplication.php b/src/applications/system/application/PhabricatorSystemApplication.php index b6cc13050f..88f07ae17c 100644 --- a/src/applications/system/application/PhabricatorSystemApplication.php +++ b/src/applications/system/application/PhabricatorSystemApplication.php @@ -14,6 +14,12 @@ final class PhabricatorSystemApplication extends PhabricatorApplication { return true; } + public function getEventListeners() { + return array( + new PhabricatorSystemDebugUIEventListener(), + ); + } + public function getRoutes() { return array( '/status/' => 'PhabricatorStatusController', diff --git a/src/applications/system/events/PhabricatorSystemDebugUIEventListener.php b/src/applications/system/events/PhabricatorSystemDebugUIEventListener.php new file mode 100644 index 0000000000..18b94323b6 --- /dev/null +++ b/src/applications/system/events/PhabricatorSystemDebugUIEventListener.php @@ -0,0 +1,58 @@ +listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); + } + + public function handleEvent(PhutilEvent $event) { + switch ($event->getType()) { + case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS: + $this->handleActionEvent($event); + break; + } + } + + private function handleActionEvent($event) { + $viewer = $event->getUser(); + $object = $event->getValue('object'); + + if (!PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) { + return; + } + + if (!$object || !$object->getPHID()) { + // If we have no object, or the object doesn't have a PHID, we can't + // do anything useful. + return; + } + + $phid = $object->getPHID(); + + $submenu = array(); + + $submenu[] = id(new PhabricatorActionView()) + ->setIcon('fa-asterisk') + ->setName(pht('View Handle')) + ->setHref(urisprintf('/search/handle/%s/', $phid)) + ->setWorkflow(true); + + $submenu[] = id(new PhabricatorActionView()) + ->setIcon('fa-address-card-o') + ->setName(pht('View Hovercard')) + ->setHref(urisprintf('/search/hovercard/?phids[]=%s', $phid)); + + $developer_action = id(new PhabricatorActionView()) + ->setName(pht('Advanced/Developer...')) + ->setIcon('fa-magic') + ->setOrder(9001) + ->setSubmenu($submenu); + + $actions = $event->getValue('actions'); + $actions[] = $developer_action; + $event->setValue('actions', $actions); + } + +} diff --git a/src/view/layout/PhabricatorActionListView.php b/src/view/layout/PhabricatorActionListView.php index 134c336735..22e995ab64 100644 --- a/src/view/layout/PhabricatorActionListView.php +++ b/src/view/layout/PhabricatorActionListView.php @@ -52,6 +52,14 @@ final class PhabricatorActionListView extends AphrontTagView { $action->setViewer($viewer); } + $sort = array(); + foreach ($actions as $key => $action) { + $sort[$key] = id(new PhutilSortVector()) + ->addInt($action->getOrder()); + } + $sort = msortv($sort, 'getSelf'); + $actions = array_select_keys($actions, array_keys($sort)); + require_celerity_resource('phabricator-action-list-view-css'); $items = array();