diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => 'a419cf4b', - 'core.pkg.js' => 'cf262309', + 'core.pkg.js' => 'b826f522', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => '64e69521', @@ -452,7 +452,7 @@ 'rsrc/js/core/DragAndDropFileUpload.js' => 'ad10aeac', 'rsrc/js/core/DraggableList.js' => 'a16ec1c6', 'rsrc/js/core/FileUpload.js' => '477359c8', - 'rsrc/js/core/Hovercard.js' => '14ac66f5', + 'rsrc/js/core/Hovercard.js' => '6914d0dd', 'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2', 'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', @@ -747,7 +747,7 @@ 'phabricator-file-upload' => '477359c8', 'phabricator-filetree-view-css' => 'fccf9f82', 'phabricator-flag-css' => '5337623f', - 'phabricator-hovercard' => '14ac66f5', + 'phabricator-hovercard' => '6914d0dd', 'phabricator-hovercard-view-css' => '1239cd52', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => 'c1700f6f', @@ -935,13 +935,6 @@ 'javelin-dom', 'javelin-history', ), - '14ac66f5' => array( - 'javelin-install', - 'javelin-dom', - 'javelin-vector', - 'javelin-request', - 'javelin-uri', - ), '1ad0a787' => array( 'javelin-install', 'javelin-reactor', @@ -1311,6 +1304,13 @@ '6882e80a' => array( 'javelin-dom', ), + '6914d0dd' => array( + 'javelin-install', + 'javelin-dom', + 'javelin-vector', + 'javelin-request', + 'javelin-uri', + ), '69adf288' => array( 'javelin-install', ), diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -262,7 +262,6 @@ 'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php', 'ConpherenceFormDragAndDropUploadControl' => 'applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php', 'ConpherenceFulltextQuery' => 'applications/conpherence/query/ConpherenceFulltextQuery.php', - 'ConpherenceHovercardEventListener' => 'applications/conpherence/events/ConpherenceHovercardEventListener.php', 'ConpherenceImageData' => 'applications/conpherence/constants/ConpherenceImageData.php', 'ConpherenceIndex' => 'applications/conpherence/storage/ConpherenceIndex.php', 'ConpherenceLayoutView' => 'applications/conpherence/view/ConpherenceLayoutView.php', @@ -420,7 +419,7 @@ 'DifferentialHostField' => 'applications/differential/customfield/DifferentialHostField.php', 'DifferentialHostedGitLandingStrategy' => 'applications/differential/landing/DifferentialHostedGitLandingStrategy.php', 'DifferentialHostedMercurialLandingStrategy' => 'applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php', - 'DifferentialHovercardEventListener' => 'applications/differential/event/DifferentialHovercardEventListener.php', + 'DifferentialHovercardEngineExtension' => 'applications/differential/engineextension/DifferentialHovercardEngineExtension.php', 'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php', 'DifferentialHunkParser' => 'applications/differential/parser/DifferentialHunkParser.php', 'DifferentialHunkParserTestCase' => 'applications/differential/parser/__tests__/DifferentialHunkParserTestCase.php', @@ -620,7 +619,7 @@ 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 'DiffusionHistoryQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php', 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', - 'DiffusionHovercardEventListener' => 'applications/diffusion/events/DiffusionHovercardEventListener.php', + 'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php', 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php', @@ -1292,7 +1291,7 @@ 'ManiphestExcelFormatTestCase' => 'applications/maniphest/export/__tests__/ManiphestExcelFormatTestCase.php', 'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php', - 'ManiphestHovercardEventListener' => 'applications/maniphest/event/ManiphestHovercardEventListener.php', + 'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php', 'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php', 'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php', 'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php', @@ -2370,6 +2369,8 @@ 'PhabricatorHomeMainController' => 'applications/home/controller/PhabricatorHomeMainController.php', 'PhabricatorHomePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php', 'PhabricatorHomeQuickCreateController' => 'applications/home/controller/PhabricatorHomeQuickCreateController.php', + 'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php', + 'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php', 'PhabricatorHovercardUIExample' => 'applications/uiexample/examples/PhabricatorHovercardUIExample.php', 'PhabricatorHovercardView' => 'view/widget/hovercard/PhabricatorHovercardView.php', 'PhabricatorHunksManagementMigrateWorkflow' => 'applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php', @@ -2711,7 +2712,7 @@ 'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', 'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', 'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', - 'PhabricatorPeopleHovercardEventListener' => 'applications/people/event/PhabricatorPeopleHovercardEventListener.php', + 'PhabricatorPeopleHovercardEngineExtension' => 'applications/people/engineextension/PhabricatorPeopleHovercardEngineExtension.php', 'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php', 'PhabricatorPeopleInviteListController' => 'applications/people/controller/PhabricatorPeopleInviteListController.php', 'PhabricatorPeopleInviteSendController' => 'applications/people/controller/PhabricatorPeopleInviteSendController.php', @@ -4172,7 +4173,6 @@ 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceFormDragAndDropUploadControl' => 'AphrontFormControl', 'ConpherenceFulltextQuery' => 'PhabricatorOffsetPagedQuery', - 'ConpherenceHovercardEventListener' => 'PhabricatorEventListener', 'ConpherenceImageData' => 'ConpherenceConstants', 'ConpherenceIndex' => 'ConpherenceDAO', 'ConpherenceLayoutView' => 'AphrontView', @@ -4347,7 +4347,7 @@ 'DifferentialHostField' => 'DifferentialCustomField', 'DifferentialHostedGitLandingStrategy' => 'DifferentialLandingStrategy', 'DifferentialHostedMercurialLandingStrategy' => 'DifferentialLandingStrategy', - 'DifferentialHovercardEventListener' => 'PhabricatorEventListener', + 'DifferentialHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DifferentialHunk' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', @@ -4568,7 +4568,7 @@ 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionHistoryTableView' => 'DiffusionView', - 'DiffusionHovercardEventListener' => 'PhabricatorEventListener', + 'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DiffusionLastModifiedController' => 'DiffusionController', @@ -5361,7 +5361,7 @@ 'ManiphestExcelFormatTestCase' => 'PhabricatorTestCase', 'ManiphestExportController' => 'ManiphestController', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod', - 'ManiphestHovercardEventListener' => 'PhabricatorEventListener', + 'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestNameIndex' => 'ManiphestDAO', 'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType', @@ -6624,6 +6624,8 @@ 'PhabricatorHomeMainController' => 'PhabricatorHomeController', 'PhabricatorHomePreferencesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorHomeQuickCreateController' => 'PhabricatorHomeController', + 'PhabricatorHovercardEngineExtension' => 'Phobject', + 'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorHovercardUIExample' => 'PhabricatorUIExample', 'PhabricatorHovercardView' => 'AphrontView', 'PhabricatorHunksManagementMigrateWorkflow' => 'PhabricatorHunksManagementWorkflow', @@ -7010,7 +7012,7 @@ 'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', 'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', 'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', - 'PhabricatorPeopleHovercardEventListener' => 'PhabricatorEventListener', + 'PhabricatorPeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController', 'PhabricatorPeopleInviteListController' => 'PhabricatorPeopleInviteController', 'PhabricatorPeopleInviteSendController' => 'PhabricatorPeopleInviteController', diff --git a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php --- a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php +++ b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php @@ -28,12 +28,6 @@ ); } - public function getEventListeners() { - return array( - new ConpherenceHovercardEventListener(), - ); - } - public function getRoutes() { return array( '/Z(?P[1-9]\d*)' => 'ConpherenceViewController', diff --git a/src/applications/conpherence/events/ConpherenceHovercardEventListener.php b/src/applications/conpherence/events/ConpherenceHovercardEventListener.php deleted file mode 100644 --- a/src/applications/conpherence/events/ConpherenceHovercardEventListener.php +++ /dev/null @@ -1,41 +0,0 @@ -listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: - $this->handleHovercardEvent($event); - break; - } - } - - private function handleHovercardEvent($event) { - $hovercard = $event->getValue('hovercard'); - $user = $event->getValue('object'); - - if (!($user instanceof PhabricatorUser)) { - return; - } - - $conpherence_uri = id(new PhutilURI('/conpherence/new/')) - ->setQueryParam('participant', $user->getPHID()); - $name = pht('Send a Message'); - $hovercard->addAction($name, $conpherence_uri, true); - - $event->setValue('hovercard', $hovercard); - } - -} diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -44,7 +44,6 @@ public function getEventListeners() { return array( new DifferentialActionMenuEventListener(), - new DifferentialHovercardEventListener(), new DifferentialLandingActionMenuEventListener(), ); } diff --git a/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php b/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/differential/engineextension/DifferentialHovercardEngineExtension.php @@ -0,0 +1,77 @@ +getViewer(); + $phids = mpull($objects, 'getPHID'); + + $revisions = id(new DifferentialRevisionQuery()) + ->setViewer($viewer) + ->withPHIDs($phids) + ->needReviewerStatus(true) + ->execute(); + $revisions = mpull($revisions, null, 'getPHID'); + + return array( + 'revisions' => $revisions, + ); + } + + public function renderHovercard( + PhabricatorHovercardView $hovercard, + PhabricatorObjectHandle $handle, + $object, + $data) { + + $viewer = $this->getViewer(); + + $revision = idx($data['revisions'], $object->getPHID()); + if (!$revision) { + return; + } + + $hovercard->setTitle('D'.$revision->getID()); + $hovercard->setDetail($revision->getTitle()); + + $hovercard->addField( + pht('Author'), + $viewer->renderHandle($revision->getAuthorPHID())); + + $reviewer_phids = $revision->getReviewerStatus(); + $reviewer_phids = mpull($reviewer_phids, 'getReviewerPHID'); + + $hovercard->addField( + pht('Reviewers'), + $viewer->renderHandleList($reviewer_phids)->setAsInline(true)); + + $summary = $revision->getSummary(); + if (strlen($summary)) { + $summary = id(new PhutilUTF8StringTruncator()) + ->setMaximumGlyphs(120) + ->truncateString($summary); + + $hovercard->addField(pht('Summary'), $summary); + } + + $tag = DifferentialRevisionDetailView::renderTagForRevision($revision); + $hovercard->addTag($tag); + } + +} diff --git a/src/applications/differential/event/DifferentialHovercardEventListener.php b/src/applications/differential/event/DifferentialHovercardEventListener.php deleted file mode 100644 --- a/src/applications/differential/event/DifferentialHovercardEventListener.php +++ /dev/null @@ -1,71 +0,0 @@ -listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: - $this->handleHovercardEvent($event); - break; - } - } - - private function handleHovercardEvent($event) { - $viewer = $event->getUser(); - $hovercard = $event->getValue('hovercard'); - $object_handle = $event->getValue('handle'); - $phid = $object_handle->getPHID(); - $rev = $event->getValue('object'); - - if (!($rev instanceof DifferentialRevision)) { - return; - } - - $rev->loadRelationships(); - $reviewer_phids = $rev->getReviewers(); - $e_task = DifferentialRevisionHasTaskEdgeType::EDGECONST; - $edge_query = id(new PhabricatorEdgeQuery()) - ->withSourcePHIDs(array($phid)) - ->withEdgeTypes( - array( - $e_task, - )); - $edge_query->execute(); - $tasks = $edge_query->getDestinationPHIDs(); - - $hovercard->setTitle('D'.$rev->getID()); - $hovercard->setDetail($rev->getTitle()); - - $hovercard->addField( - pht('Author'), - $viewer->renderHandle($rev->getAuthorPHID())); - - $hovercard->addField( - pht('Reviewers'), - $viewer->renderHandleList($reviewer_phids)->setAsInline(true)); - - if ($tasks) { - $hovercard->addField( - pht('Tasks'), - $viewer->renderHandleList($tasks)->setAsInline(true)); - } - - if ($rev->getSummary()) { - $hovercard->addField(pht('Summary'), - id(new PhutilUTF8StringTruncator()) - ->setMaximumGlyphs(120) - ->truncateString($rev->getSummary())); - } - - $hovercard->addTag( - DifferentialRevisionDetailView::renderTagForRevision($rev)); - - $event->setValue('hovercard', $hovercard); - } - -} diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -37,12 +37,6 @@ ); } - public function getEventListeners() { - return array( - new DiffusionHovercardEventListener(), - ); - } - public function getRemarkupRules() { return array( new DiffusionCommitRemarkupRule(), diff --git a/src/applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php b/src/applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php @@ -0,0 +1,53 @@ +getViewer(); + + $author_phid = $commit->getAuthorPHID(); + if ($author_phid) { + $author = $viewer->loadHandle($author)->renderLink(); + } else { + $commit_data = $commit->loadCommitData(); + $author = phutil_tag('em', array(), $commit_data->getAuthorName()); + } + + $hovercard->setTitle($handle->getName()); + $hovercard->setDetail($commit->getSummary()); + + $hovercard->addField(pht('Author'), $author); + $hovercard->addField(pht('Date'), + phabricator_date($commit->getEpoch(), $viewer)); + + if ($commit->getAuditStatus() != + PhabricatorAuditCommitStatusConstants::NONE) { + + $hovercard->addField(pht('Audit Status'), + PhabricatorAuditCommitStatusConstants::getStatusName( + $commit->getAuditStatus())); + } + } + +} diff --git a/src/applications/diffusion/events/DiffusionHovercardEventListener.php b/src/applications/diffusion/events/DiffusionHovercardEventListener.php deleted file mode 100644 --- a/src/applications/diffusion/events/DiffusionHovercardEventListener.php +++ /dev/null @@ -1,75 +0,0 @@ -listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: - $this->handleHovercardEvent($event); - break; - } - } - - private function handleHovercardEvent($event) { - $viewer = $event->getUser(); - $hovercard = $event->getValue('hovercard'); - $object_handle = $event->getValue('handle'); - $commit = $event->getValue('object'); - - if (!($commit instanceof PhabricatorRepositoryCommit)) { - return; - } - - $commit_data = $commit->loadCommitData(); - - $revision = PhabricatorEdgeQuery::loadDestinationPHIDs( - $commit->getPHID(), - DiffusionCommitHasRevisionEdgeType::EDGECONST); - $revision = reset($revision); - - $author = $commit->getAuthorPHID(); - - $phids = array_filter(array( - $revision, - $author, - )); - - $handles = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs($phids) - ->execute(); - - if ($author) { - $author = $handles[$author]->renderLink(); - } else { - $author = phutil_tag('em', array(), $commit_data->getAuthorName()); - } - - $hovercard->setTitle($object_handle->getName()); - $hovercard->setDetail($commit->getSummary()); - - $hovercard->addField(pht('Author'), $author); - $hovercard->addField(pht('Date'), - phabricator_date($commit->getEpoch(), $viewer)); - - if ($commit->getAuditStatus() != - PhabricatorAuditCommitStatusConstants::NONE) { - - $hovercard->addField(pht('Audit Status'), - PhabricatorAuditCommitStatusConstants::getStatusName( - $commit->getAuditStatus())); - } - - if ($revision) { - $rev_handle = $handles[$revision]; - $hovercard->addField(pht('Revision'), $rev_handle->renderLink()); - } - - $event->setValue('hovercard', $hovercard); - } - -} diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php --- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php +++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php @@ -36,12 +36,6 @@ ); } - public function getEventListeners() { - return array( - new ManiphestHovercardEventListener(), - ); - } - public function getRemarkupRules() { return array( new ManiphestRemarkupRule(), diff --git a/src/applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php b/src/applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php @@ -0,0 +1,47 @@ +getViewer(); + + $hovercard + ->setTitle($task->getMonogram()) + ->setDetail($task->getTitle()); + + $owner_phid = $task->getOwnerPHID(); + if ($owner_phid) { + $owner = $viewer->renderHandle($owner_phid); + } else { + $owner = phutil_tag('em', array(), pht('None')); + } + $hovercard->addField(pht('Assigned To'), $owner); + + $hovercard->addField( + pht('Priority'), + ManiphestTaskPriority::getTaskPriorityName($task->getPriority())); + + $hovercard->addTag(ManiphestView::renderTagForTask($task)); + } + +} diff --git a/src/applications/maniphest/event/ManiphestHovercardEventListener.php b/src/applications/maniphest/event/ManiphestHovercardEventListener.php deleted file mode 100644 --- a/src/applications/maniphest/event/ManiphestHovercardEventListener.php +++ /dev/null @@ -1,93 +0,0 @@ -listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); - } - - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: - $this->handleHovercardEvent($event); - break; - } - } - - private function handleHovercardEvent(PhutilEvent $event) { - $viewer = $event->getUser(); - $hovercard = $event->getValue('hovercard'); - $handle = $event->getValue('handle'); - $phid = $handle->getPHID(); - $task = $event->getValue('object'); - - if (!($task instanceof ManiphestTask)) { - return; - } - - $e_project = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - // Fun with "Unbeta Pholio", hua hua - $e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST; - $e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST; - - $edge_query = id(new PhabricatorEdgeQuery()) - ->withSourcePHIDs(array($phid)) - ->withEdgeTypes( - array( - $e_project, - $e_dep_on, - $e_dep_by, - )); - $edges = idx($edge_query->execute(), $phid); - $edge_phids = $edge_query->getDestinationPHIDs(); - - $owner_phid = $task->getOwnerPHID(); - - $hovercard - ->setTitle(pht('T%d', $task->getID())) - ->setDetail($task->getTitle()); - - if ($owner_phid) { - $owner = $viewer->renderHandle($owner_phid); - } else { - $owner = phutil_tag('em', array(), pht('None')); - } - $hovercard->addField(pht('Assigned To'), $owner); - $hovercard->addField( - pht('Priority'), - ManiphestTaskPriority::getTaskPriorityName($task->getPriority())); - - if ($edge_phids) { - $edge_types = array( - $e_project => pht('Projects'), - $e_dep_by => pht('Blocks'), - $e_dep_on => pht('Blocked By'), - ); - - $max_count = 6; - foreach ($edge_types as $edge_type => $edge_name) { - if ($edges[$edge_type]) { - // TODO: This can be made more sophisticated. We still load all - // edges into memory. Only load the ones we need. - $edge_overflow = array(); - if (count($edges[$edge_type]) > $max_count) { - $edges[$edge_type] = array_slice($edges[$edge_type], 0, 6, true); - $edge_overflow = ', ...'; - } - - $hovercard->addField( - $edge_name, - array( - $viewer->renderHandleList(array_keys($edges[$edge_type])), - $edge_overflow, - )); - } - } - } - - $hovercard->addTag(ManiphestView::renderTagForTask($task)); - - $event->setValue('hovercard', $hovercard); - } - -} diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -34,12 +34,6 @@ return false; } - public function getEventListeners() { - return array( - new PhabricatorPeopleHovercardEventListener(), - ); - } - public function getRoutes() { return array( '/people/' => array( diff --git a/src/applications/people/event/PhabricatorPeopleHovercardEventListener.php b/src/applications/people/engineextension/PhabricatorPeopleHovercardEngineExtension.php rename from src/applications/people/event/PhabricatorPeopleHovercardEventListener.php rename to src/applications/people/engineextension/PhabricatorPeopleHovercardEngineExtension.php --- a/src/applications/people/event/PhabricatorPeopleHovercardEventListener.php +++ b/src/applications/people/engineextension/PhabricatorPeopleHovercardEngineExtension.php @@ -1,45 +1,58 @@ listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); + const EXTENSIONKEY = 'people'; + + public function isExtensionEnabled() { + return true; } - public function handleEvent(PhutilEvent $event) { - switch ($event->getType()) { - case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: - $this->handleHovercardEvent($event); - break; - } + public function getExtensionName() { + return pht('User Accounts'); } - private function handleHovercardEvent($event) { - $viewer = $event->getUser(); - $hovercard = $event->getValue('hovercard'); - $object_handle = $event->getValue('handle'); - $phid = $object_handle->getPHID(); - $user = $event->getValue('object'); + public function canRenderObjectHovercard($object) { + return ($object instanceof PhabricatorUser); + } - if (!($user instanceof PhabricatorUser)) { - return; - } + public function willRenderHovercards(array $objects) { + $viewer = $this->getViewer(); + $phids = mpull($objects, 'getPHID'); - // Reload to get availability. - $user = id(new PhabricatorPeopleQuery()) + $users = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) - ->withIDs(array($user->getID())) + ->withPHIDs($phids) ->needAvailability(true) ->needProfile(true) ->needBadges(true) - ->executeOne(); + ->execute(); + $users = mpull($users, null, 'getPHID'); + + return array( + 'users' => $users, + ); + } + + public function renderHovercard( + PhabricatorHovercardView $hovercard, + PhabricatorObjectHandle $handle, + $object, + $data) { + $viewer = $this->getViewer(); + + $user = idx($data['users'], $object->getPHID()); + if (!$user) { + return; + } $hovercard->setTitle($user->getUsername()); + $profile = $user->getUserProfile(); $detail = $user->getRealName(); if ($profile->getTitle()) { - $detail .= ' - '.$profile->getTitle().'.'; + $detail .= ' - '.$profile->getTitle(); } $hovercard->setDetail($detail); @@ -70,8 +83,6 @@ foreach ($badges as $badge) { $hovercard->addBadge($badge); } - - $event->setValue('hovercard', $hovercard); } private function buildBadges( @@ -101,5 +112,4 @@ return $items; } - } diff --git a/src/applications/search/application/PhabricatorSearchApplication.php b/src/applications/search/application/PhabricatorSearchApplication.php --- a/src/applications/search/application/PhabricatorSearchApplication.php +++ b/src/applications/search/application/PhabricatorSearchApplication.php @@ -35,7 +35,7 @@ 'select/(?P\w+)/(?:(?P\w+)/)?' => 'PhabricatorSearchSelectController', 'index/(?P[^/]+)/' => 'PhabricatorSearchIndexController', - 'hovercard/(?Pretrieve|test)/' + 'hovercard/' => 'PhabricatorSearchHovercardController', 'edit/(?P[^/]+)/' => 'PhabricatorSearchEditController', 'delete/(?P[^/]+)/(?P[^/]+)/' diff --git a/src/applications/search/controller/PhabricatorSearchHovercardController.php b/src/applications/search/controller/PhabricatorSearchHovercardController.php --- a/src/applications/search/controller/PhabricatorSearchHovercardController.php +++ b/src/applications/search/controller/PhabricatorSearchHovercardController.php @@ -15,13 +15,43 @@ ->setViewer($viewer) ->withPHIDs($phids) ->execute(); + $objects = id(new PhabricatorObjectQuery()) ->setViewer($viewer) ->withPHIDs($phids) ->execute(); + $objects = mpull($objects, null, 'getPHID'); - $cards = array(); + $extensions = + PhabricatorHovercardEngineExtension::getAllEnabledExtensions(); + + $extension_maps = array(); + foreach ($extensions as $key => $extension) { + $extension->setViewer($viewer); + + $extension_phids = array(); + foreach ($objects as $phid => $object) { + if ($extension->canRenderObjectHovercard($object)) { + $extension_phids[$phid] = $phid; + } + } + + $extension_maps[$key] = $extension_phids; + } + + $extension_data = array(); + foreach ($extensions as $key => $extension) { + $extension_phids = $extension_maps[$key]; + if (!$extension_phids) { + unset($extensions[$key]); + continue; + } + $extension_data[$key] = $extension->willRenderHovercards( + array_select_keys($objects, $extension_phids)); + } + + $cards = array(); foreach ($phids as $phid) { $handle = $handles[$phid]; $object = $objects[$phid]; @@ -32,43 +62,39 @@ if ($object) { $hovercard->setObject($object); - } - // Send it to the other side of the world, thanks to PhutilEventEngine - $event = new PhabricatorEvent( - PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD, - array( - 'hovercard' => $hovercard, - 'handle' => $handle, - 'object' => $object, - )); - $event->setUser($viewer); - PhutilEventEngine::dispatchEvent($event); + foreach ($extension_maps as $key => $extension_phids) { + if (isset($extension_phids[$phid])) { + $extensions[$key]->renderHovercard( + $hovercard, + $handle, + $object, + $extension_data[$key]); + } + } + } $cards[$phid] = $hovercard; } - // Browser-friendly for non-Ajax requests - if (!$request->isAjax()) { - foreach ($cards as $key => $hovercard) { - $cards[$key] = phutil_tag('div', - array( - 'class' => 'ml', - ), - $hovercard); - } - - return $this->buildApplicationPage( - $cards, - array( - 'device' => false, - )); - } else { + if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent( array( 'cards' => $cards, )); } + + foreach ($cards as $key => $hovercard) { + $cards[$key] = phutil_tag('div', + array( + 'class' => 'ml', + ), + $hovercard); + } + + return $this->newPage() + ->appendChild($cards) + ->setShowFooter(false); } } diff --git a/src/applications/search/engineextension/PhabricatorHovercardEngineExtension.php b/src/applications/search/engineextension/PhabricatorHovercardEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/search/engineextension/PhabricatorHovercardEngineExtension.php @@ -0,0 +1,60 @@ +getPhobjectClassConstant('EXTENSIONKEY'); + } + + final public function setViewer($viewer) { + $this->viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + abstract public function isExtensionEnabled(); + + abstract public function getExtensionName(); + + abstract public function canRenderObjectHovercard($object); + + public function getExtensionOrder() { + return 5000; + } + + public function willRenderHovercards(array $objects) { + return null; + } + + abstract public function renderHovercard( + PhabricatorHovercardView $hovercard, + PhabricatorObjectHandle $handle, + $object, + $data); + + final public static function getAllExtensions() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getExtensionKey') + ->setSortMethod('getExtensionOrder') + ->execute(); + } + + final public static function getAllEnabledExtensions() { + $extensions = self::getAllExtensions(); + + foreach ($extensions as $key => $extension) { + if (!$extension->isExtensionEnabled()) { + unset($extensions[$key]); + } + } + + return $extensions; + } + +} diff --git a/src/applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php b/src/applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php new file mode 100644 --- /dev/null +++ b/src/applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php @@ -0,0 +1,55 @@ +getViewer(); + + $extensions = PhabricatorHovercardEngineExtension::getAllExtensions(); + + $rows = array(); + foreach ($extensions as $extension) { + $rows[] = array( + $extension->getExtensionOrder(), + $extension->getExtensionKey(), + get_class($extension), + $extension->getExtensionName(), + $extension->isExtensionEnabled() + ? pht('Yes') + : pht('No'), + ); + } + + $table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('Order'), + pht('Key'), + pht('Class'), + pht('Name'), + pht('Enabled'), + )) + ->setColumnClasses( + array( + null, + null, + null, + 'wide pri', + null, + )); + + return id(new PHUIObjectBoxView()) + ->setHeaderText(pht('HovercardEngine Extensions')) + ->setTable($table); + } + +} diff --git a/src/infrastructure/events/constant/PhabricatorEventType.php b/src/infrastructure/events/constant/PhabricatorEventType.php --- a/src/infrastructure/events/constant/PhabricatorEventType.php +++ b/src/infrastructure/events/constant/PhabricatorEventType.php @@ -20,8 +20,6 @@ const TYPE_UI_DIDRENDEROBJECTS = 'ui.didRenderObjects'; const TYPE_UI_WILLRENDERPROPERTIES = 'ui.willRenderProperties'; - const TYPE_UI_DIDRENDERHOVERCARD = 'ui.didRenderHovercard'; - const TYPE_PEOPLE_DIDRENDERMENU = 'people.didRenderMenu'; const TYPE_AUTH_WILLREGISTERUSER = 'auth.willRegisterUser'; const TYPE_AUTH_WILLLOGINUSER = 'auth.willLoginUser'; diff --git a/webroot/rsrc/js/core/Hovercard.js b/webroot/rsrc/js/core/Hovercard.js --- a/webroot/rsrc/js/core/Hovercard.js +++ b/webroot/rsrc/js/core/Hovercard.js @@ -15,7 +15,7 @@ _activeRoot : null, _visiblePHID : null, - fetchUrl : '/search/hovercard/retrieve/', + fetchUrl : '/search/hovercard/', /** * Hovercard storage. {"PHID-XXXX-YYYY":"<...>", ...}