From 8f5e28bf59b1868ff7676751daa1196846c2b3f9 Mon Sep 17 00:00:00 2001 From: Nick Harper Date: Thu, 1 Dec 2011 16:57:06 -0800 Subject: [PATCH] Add differential.query conduit method Summary: Created a differential.query conduit method that is built on top of DifferentialRevisionQuery. I also added support for querying by author, ccs, and reviewers to DifferentialRevisionQuery, so feature parity can be brought up to match differential.find and its backing class DifferentialRevisionListData. Test Plan: Tried a few calls to the conduit call using the web interface, and got back reasonable looking data. Reviewers: epriestley, jungejason, btrahan Reviewed By: epriestley CC: aran, nh, epriestley Differential Revision: 1158 --- src/__phutil_library_map__.php | 2 + .../ConduitAPI_differential_query_Method.php | 144 ++++++++++++++++++ .../method/differential/query/__init__.php | 15 ++ .../revision/DifferentialRevisionQuery.php | 141 +++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 src/applications/conduit/method/differential/query/ConduitAPI_differential_query_Method.php create mode 100644 src/applications/conduit/method/differential/query/__init__.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 67960fead6..cb0892e98b 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -107,6 +107,7 @@ phutil_register_library_map(array( 'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/conduit/method/differential/getrevisionfeedback', 'ConduitAPI_differential_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted', 'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage', + 'ConduitAPI_differential_query_Method' => 'applications/conduit/method/differential/query', 'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty', 'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision', 'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'applications/conduit/method/differential/updatetaskrevisionassoc', @@ -834,6 +835,7 @@ phutil_register_library_map(array( 'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod', + 'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'ConduitAPIMethod', diff --git a/src/applications/conduit/method/differential/query/ConduitAPI_differential_query_Method.php b/src/applications/conduit/method/differential/query/ConduitAPI_differential_query_Method.php new file mode 100644 index 0000000000..055a069858 --- /dev/null +++ b/src/applications/conduit/method/differential/query/ConduitAPI_differential_query_Method.php @@ -0,0 +1,144 @@ + 'optional phid', + 'ccs' => 'optional list', + 'reviewers' => 'optional list', + 'paths' => 'optional list', + 'status' => 'optional enum<'.$status_types.'>', + 'order' => 'optional enum<'.$order_types.'>', + 'limit' => 'optional uint', + 'offset' => 'optional uint', + 'ids' => 'optional list', + 'phids' => 'optional list', + ); + } + + public function defineReturnType() { + return 'list'; + } + + public function defineErrorTypes() { + return array( + ); + } + + protected function execute(ConduitAPIRequest $request) { + $author = $request->getValue('author'); + $ccs = $request->getValue('ccs'); + $reviewers = $request->getValue('reviewers'); + $paths = $request->getValue('paths'); + $status = $request->getValue('status'); + $order = $request->getValue('order'); + $limit = $request->getValue('limit'); + $offset = $request->getValue('offset'); + $ids = $request->getValue('ids'); + $phids = $request->getValue('phids'); + + $query = new DifferentialRevisionQuery(); + $query->withAuthor($author); + if ($ccs) { + $query->withCCs($ccs); + } + if ($reviewers) { + $query->withReviewers($reviewers); + } + if ($paths) { + foreach ($paths as $path) { + $query->withPath($path); + } + } + if ($status) { + $query->withStatus($status); + } + if ($order) { + $query->setOrder($order); + } + if ($limit) { + $query->setLimit($limit); + } + if ($offset) { + $query->setOffset($offset); + } + if ($ids) { + $query->withIDs($ids); + } + if ($phids) { + $query->withPHIDs($phids); + } + + $revisions = $query->execute(); + + $results = array(); + foreach ($revisions as $revision) { + $diff = $revision->loadActiveDiff(); + if (!$diff) { + continue; + } + + $revision->loadRelationships(); + + $id = $revision->getID(); + $results[] = array( + 'id' => $id, + 'phid' => $revision->getPHID(), + 'title' => $revision->getTitle(), + 'uri' => PhabricatorEnv::getProductionURI('/D'.$id), + 'dateCreated' => $revision->getDateCreated(), + 'authorPHID' => $revision->getAuthorPHID(), + 'status' => $revision->getStatus(), + 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus( + $revision->getStatus()), + 'sourcePath' => $diff->getSourcePath(), + 'summary' => $revision->getSummary(), + 'testPlan' => $revision->getTestPlan(), + 'lineCount' => $revision->getLineCount(), + 'diffs' => array_keys($revision->loadDiffs()), + 'commits' => $revision->loadCommitPHIDs(), + 'reviewers' => array_values($revision->getReviewers()), + 'ccs' => array_values($revision->getCCPHIDs()), + ); + } + + return $results; + } + +} diff --git a/src/applications/conduit/method/differential/query/__init__.php b/src/applications/conduit/method/differential/query/__init__.php new file mode 100644 index 0000000000..edaf82fedc --- /dev/null +++ b/src/applications/conduit/method/differential/query/__init__.php @@ -0,0 +1,15 @@ +author = $author_phid; + return $this; + } + + /** + * Filter results to revisions which CC all of the listed people. Calling this + * function will clear anything set by previous calls to withCCs or withCC. + * + * @param array List of PHIDs of subscribers + * @return this + * @task config + */ + public function withCCs(array $cc_phids) { + $this->ccs = $cc_phids; + return $this; + } + + /** + * Add a PHID to the list of CCs that must be present on the revision. Calling + * this multiple times will continue to add CC PHID constraints, and will not + * clear anything set by previous calls to withCCs or withCC. + * + * @param phid CC PHID + * @return this + * @task config + */ + public function withCC($cc) { + $this->ccs[] = $cc; + return $this; + } + + /** + * Filter results to revisions that have all of the provided PHIDs as + * reviewers. Calling this function will clear anything set by previous calls + * to withReviewers or withReviewer. + * + * @param array List of PHIDs of reviewers + * @return this + * @task config + */ + public function withReviewers(array $reviewer_phids) { + $this->reviewers = $reviewer_phids; + return $this; + } + + /** + * Add a PHID to the list of reviewers that must be present on the revision. + * Calling this multiple times will continue to add reviewer PHID constraints, + * and will not clear anything set by previous calls to withReviewers or + * withReviewer. + * + * @param phid reviewer PHID + * @return this + * @task config + */ + public function withReviewer($reviewer) { + $this->reviewers[] = $reviewer; + return $this; + } /** * Filter results to revisions with a given status. Provide a class constant, @@ -92,6 +166,32 @@ final class DifferentialRevisionQuery { } + /** + * Filter results to only return revisions whose ids are in the given set. + * + * @param array List of revision ids + * @return this + * @task config + */ + public function withIDs(array $ids) { + $this->revIDs = $ids; + return $this; + } + + + /** + * Filter results to only return revisions whose PHIDs are in the given set. + * + * @param array List of revision PHIDs + * @return this + * @task config + */ + public function withPHIDs(array $phids) { + $this->phids = $phids; + return $this; + } + + /** * Set result ordering. Provide a class constant, such as * ##DifferentialRevisionQuery::ORDER_CREATED##. @@ -247,6 +347,47 @@ final class DifferentialRevisionQuery { $where[] = $path_clauses; } + if ($this->author) { + $where[] = qsprintf( + $conn_r, + 'authorPHID = %s', + $this->author); + } + + foreach ($this->ccs as $cc) { + $where[] = qsprintf( + $conn_r, + 'id IN '. + '(SELECT revisionID FROM %T WHERE relation = %s AND objectPHID = %s)', + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_SUBSCRIBED, + $cc); + } + + foreach ($this->reviewers as $reviewer) { + $where[] = qsprintf( + $conn_r, + 'id IN '. + '(SELECT revisionID FROM %T WHERE relation = %s AND objectPHID = %s)', + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_REVIEWER, + $reviewer); + } + + if ($this->revIDs) { + $where[] = qsprintf( + $conn_r, + 'id IN (%Ld)', + $this->revIDs); + } + + if ($this->phids) { + $where[] = qsprintf( + $conn_r, + 'phid IN (%Ls)', + $this->phids); + } + switch ($this->status) { case self::STATUS_ANY: break;