Path: blob/master/src/applications/differential/query/DifferentialRevisionSearchEngine.php
12256 views
<?php12final class DifferentialRevisionSearchEngine3extends PhabricatorApplicationSearchEngine {45public function getResultTypeDescription() {6return pht('Differential Revisions');7}89public function getApplicationClassName() {10return 'PhabricatorDifferentialApplication';11}1213protected function newResultBuckets() {14return DifferentialRevisionResultBucket::getAllResultBuckets();15}1617public function newQuery() {18return id(new DifferentialRevisionQuery())19->needFlags(true)20->needDrafts(true)21->needReviewers(true);22}2324protected function buildQueryFromParameters(array $map) {25$query = $this->newQuery();2627if ($map['responsiblePHIDs']) {28$query->withResponsibleUsers($map['responsiblePHIDs']);29}3031if ($map['authorPHIDs']) {32$query->withAuthors($map['authorPHIDs']);33}3435if ($map['reviewerPHIDs']) {36$query->withReviewers($map['reviewerPHIDs']);37}3839if ($map['repositoryPHIDs']) {40$query->withRepositoryPHIDs($map['repositoryPHIDs']);41}4243if ($map['statuses']) {44$query->withStatuses($map['statuses']);45}4647if ($map['createdStart'] || $map['createdEnd']) {48$query->withCreatedEpochBetween(49$map['createdStart'],50$map['createdEnd']);51}5253if ($map['modifiedStart'] || $map['modifiedEnd']) {54$query->withUpdatedEpochBetween(55$map['modifiedStart'],56$map['modifiedEnd']);57}5859if ($map['affectedPaths']) {60$query->withPaths($map['affectedPaths']);61}6263return $query;64}6566protected function buildCustomSearchFields() {67return array(68id(new PhabricatorSearchDatasourceField())69->setLabel(pht('Responsible Users'))70->setKey('responsiblePHIDs')71->setAliases(array('responsiblePHID', 'responsibles', 'responsible'))72->setDatasource(new DifferentialResponsibleDatasource())73->setDescription(74pht('Find revisions that a given user is responsible for.')),75id(new PhabricatorUsersSearchField())76->setLabel(pht('Authors'))77->setKey('authorPHIDs')78->setAliases(array('author', 'authors', 'authorPHID'))79->setDescription(80pht('Find revisions with specific authors.')),81id(new PhabricatorSearchDatasourceField())82->setLabel(pht('Reviewers'))83->setKey('reviewerPHIDs')84->setAliases(array('reviewer', 'reviewers', 'reviewerPHID'))85->setDatasource(new DifferentialReviewerFunctionDatasource())86->setDescription(87pht('Find revisions with specific reviewers.')),88id(new PhabricatorSearchDatasourceField())89->setLabel(pht('Repositories'))90->setKey('repositoryPHIDs')91->setAliases(array('repository', 'repositories', 'repositoryPHID'))92->setDatasource(new DiffusionRepositoryFunctionDatasource())93->setDescription(94pht('Find revisions from specific repositories.')),95id(new PhabricatorSearchDatasourceField())96->setLabel(pht('Statuses'))97->setKey('statuses')98->setAliases(array('status'))99->setDatasource(new DifferentialRevisionStatusFunctionDatasource())100->setDescription(101pht('Find revisions with particular statuses.')),102id(new PhabricatorSearchDateField())103->setLabel(pht('Created After'))104->setKey('createdStart')105->setDescription(106pht('Find revisions created at or after a particular time.')),107id(new PhabricatorSearchDateField())108->setLabel(pht('Created Before'))109->setKey('createdEnd')110->setDescription(111pht('Find revisions created at or before a particular time.')),112id(new PhabricatorSearchDateField())113->setLabel(pht('Modified After'))114->setKey('modifiedStart')115->setIsHidden(true)116->setDescription(117pht('Find revisions modified at or after a particular time.')),118id(new PhabricatorSearchDateField())119->setLabel(pht('Modified Before'))120->setKey('modifiedEnd')121->setIsHidden(true)122->setDescription(123pht('Find revisions modified at or before a particular time.')),124id(new PhabricatorSearchStringListField())125->setKey('affectedPaths')126->setLabel(pht('Affected Paths'))127->setDescription(128pht('Search for revisions affecting particular paths.'))129->setIsHidden(true),130);131}132133protected function getURI($path) {134return '/differential/'.$path;135}136137protected function getBuiltinQueryNames() {138$names = array();139140if ($this->requireViewer()->isLoggedIn()) {141$names['active'] = pht('Active Revisions');142$names['authored'] = pht('Authored');143}144145$names['all'] = pht('All Revisions');146147return $names;148}149150public function buildSavedQueryFromBuiltin($query_key) {151$query = $this->newSavedQuery();152$query->setQueryKey($query_key);153154$viewer = $this->requireViewer();155156switch ($query_key) {157case 'active':158$bucket_key = DifferentialRevisionRequiredActionResultBucket::BUCKETKEY;159160return $query161->setParameter('responsiblePHIDs', array($viewer->getPHID()))162->setParameter('statuses', array('open()'))163->setParameter('bucket', $bucket_key);164case 'authored':165return $query166->setParameter('authorPHIDs', array($viewer->getPHID()));167case 'all':168return $query;169}170171return parent::buildSavedQueryFromBuiltin($query_key);172}173174private function getStatusOptions() {175return array(176DifferentialLegacyQuery::STATUS_ANY => pht('All'),177DifferentialLegacyQuery::STATUS_OPEN => pht('Open'),178DifferentialLegacyQuery::STATUS_ACCEPTED => pht('Accepted'),179DifferentialLegacyQuery::STATUS_NEEDS_REVIEW => pht('Needs Review'),180DifferentialLegacyQuery::STATUS_NEEDS_REVISION => pht('Needs Revision'),181DifferentialLegacyQuery::STATUS_CLOSED => pht('Closed'),182DifferentialLegacyQuery::STATUS_ABANDONED => pht('Abandoned'),183);184}185186protected function renderResultList(187array $revisions,188PhabricatorSavedQuery $query,189array $handles) {190assert_instances_of($revisions, 'DifferentialRevision');191192$viewer = $this->requireViewer();193$template = id(new DifferentialRevisionListView())194->setViewer($viewer)195->setNoBox($this->isPanelContext());196197$bucket = $this->getResultBucket($query);198199$unlanded = $this->loadUnlandedDependencies($revisions);200201$views = array();202if ($bucket) {203$bucket->setViewer($viewer);204205try {206$groups = $bucket->newResultGroups($query, $revisions);207208foreach ($groups as $group) {209// Don't show groups in Dashboard Panels210if ($group->getObjects() || !$this->isPanelContext()) {211$views[] = id(clone $template)212->setHeader($group->getName())213->setNoDataString($group->getNoDataString())214->setRevisions($group->getObjects());215}216}217} catch (Exception $ex) {218$this->addError($ex->getMessage());219}220} else {221$views[] = id(clone $template)222->setRevisions($revisions);223}224225if (!$views) {226$views[] = id(new DifferentialRevisionListView())227->setViewer($viewer)228->setNoDataString(pht('No revisions found.'));229}230231foreach ($views as $view) {232$view->setUnlandedDependencies($unlanded);233}234235if (count($views) == 1) {236// Reduce this to a PHUIObjectItemListView so we can get the free237// support from ApplicationSearch.238$list = head($views)->render();239} else {240$list = $views;241}242243$result = new PhabricatorApplicationSearchResultView();244$result->setContent($list);245246return $result;247}248249protected function getNewUserBody() {250$create_button = id(new PHUIButtonView())251->setTag('a')252->setText(pht('Create a Diff'))253->setHref('/differential/diff/create/')254->setColor(PHUIButtonView::GREEN);255256$icon = $this->getApplication()->getIcon();257$app_name = $this->getApplication()->getName();258$view = id(new PHUIBigInfoView())259->setIcon($icon)260->setTitle(pht('Welcome to %s', $app_name))261->setDescription(262pht('Pre-commit code review. Revisions that are waiting on your input '.263'will appear here.'))264->addAction($create_button);265266return $view;267}268269private function loadUnlandedDependencies(array $revisions) {270$phids = array();271foreach ($revisions as $revision) {272if (!$revision->isAccepted()) {273continue;274}275276$phids[] = $revision->getPHID();277}278279if (!$phids) {280return array();281}282283$query = id(new PhabricatorEdgeQuery())284->withSourcePHIDs($phids)285->withEdgeTypes(286array(287DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST,288));289290$query->execute();291292$revision_phids = $query->getDestinationPHIDs();293if (!$revision_phids) {294return array();295}296297$viewer = $this->requireViewer();298299$blocking_revisions = id(new DifferentialRevisionQuery())300->setViewer($viewer)301->withPHIDs($revision_phids)302->withIsOpen(true)303->execute();304$blocking_revisions = mpull($blocking_revisions, null, 'getPHID');305306$result = array();307foreach ($revisions as $revision) {308$revision_phid = $revision->getPHID();309$blocking_phids = $query->getDestinationPHIDs(array($revision_phid));310$blocking = array_select_keys($blocking_revisions, $blocking_phids);311if ($blocking) {312$result[$revision_phid] = $blocking;313}314}315316return $result;317}318319protected function newExportFields() {320$fields = array(321id(new PhabricatorStringExportField())322->setKey('monogram')323->setLabel(pht('Monogram')),324id(new PhabricatorPHIDExportField())325->setKey('authorPHID')326->setLabel(pht('Author PHID')),327id(new PhabricatorStringExportField())328->setKey('author')329->setLabel(pht('Author')),330id(new PhabricatorStringExportField())331->setKey('status')332->setLabel(pht('Status')),333id(new PhabricatorStringExportField())334->setKey('statusName')335->setLabel(pht('Status Name')),336id(new PhabricatorURIExportField())337->setKey('uri')338->setLabel(pht('URI')),339id(new PhabricatorStringExportField())340->setKey('title')341->setLabel(pht('Title')),342id(new PhabricatorStringExportField())343->setKey('summary')344->setLabel(pht('Summary')),345id(new PhabricatorStringExportField())346->setKey('testPlan')347->setLabel(pht('Test Plan')),348);349350return $fields;351}352353protected function newExportData(array $revisions) {354$viewer = $this->requireViewer();355356$phids = array();357foreach ($revisions as $revision) {358$phids[] = $revision->getAuthorPHID();359}360$handles = $viewer->loadHandles($phids);361362$export = array();363foreach ($revisions as $revision) {364365$author_phid = $revision->getAuthorPHID();366if ($author_phid) {367$author_name = $handles[$author_phid]->getName();368} else {369$author_name = null;370}371372$status = $revision->getStatusObject();373$status_name = $status->getDisplayName();374$status_value = $status->getKey();375376$export[] = array(377'monogram' => $revision->getMonogram(),378'authorPHID' => $author_phid,379'author' => $author_name,380'status' => $status_value,381'statusName' => $status_name,382'uri' => PhabricatorEnv::getProductionURI($revision->getURI()),383'title' => (string)$revision->getTitle(),384'summary' => (string)$revision->getSummary(),385'testPlan' => (string)$revision->getTestPlan(),386);387}388389return $export;390}391392}393394395