protected function execute(ConduitAPIRequest $request)
 {
     $diff = null;
     $revision_id = $request->getValue('revision_id');
     $revision = id(new DifferentialRevision())->load($revision_id);
     if (!$revision) {
         throw new ConduitException('ERR_BAD_REVISION');
     }
     $revision->loadRelationships();
     $reviewer_phids = array_values($revision->getReviewers());
     $diffs = $revision->loadDiffs();
     $diff_dicts = array();
     foreach ($diffs as $diff) {
         $diff->attachChangesets($diff->loadChangesets());
         // TODO: We could batch this to improve performance.
         foreach ($diff->getChangesets() as $changeset) {
             $changeset->attachHunks($changeset->loadHunks());
         }
         $diff_dicts[] = ConduitAPI_differential_getdiff_Method::createDiffDict($diff);
     }
     $commit_dicts = array();
     $commit_phids = $revision->loadCommitPHIDs();
     $handles = id(new PhabricatorObjectHandleData($commit_phids))->loadHandles();
     foreach ($commit_phids as $commit_phid) {
         $commit_dicts[] = array('fullname' => $handles[$commit_phid]->getFullName(), 'dateCommitted' => $handles[$commit_phid]->getTimestamp());
     }
     $auxiliary_fields = $this->loadAuxiliaryFields($revision);
     $dict = array('id' => $revision->getID(), 'phid' => $revision->getPHID(), 'authorPHID' => $revision->getAuthorPHID(), 'uri' => PhabricatorEnv::getURI('/D' . $revision->getID()), 'title' => $revision->getTitle(), 'status' => $revision->getStatus(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'reviewerPHIDs' => $reviewer_phids, 'diffs' => $diff_dicts, 'commits' => $commit_dicts, 'auxiliary' => $auxiliary_fields);
     return $dict;
 }
 public function render()
 {
     $user = $this->user;
     if (!$user) {
         throw new Exception("Call setUser() before render()!");
     }
     $rows = array();
     foreach ($this->revisions as $revision) {
         $status = $revision->getStatus();
         $status = DifferentialRevisionStatus::getNameForRevisionStatus($status);
         $reviewer_phids = $revision->getReviewers();
         if ($reviewer_phids) {
             $first = reset($reviewer_phids);
             if (count($reviewer_phids) > 1) {
                 $suffix = ' (+' . (count($reviewer_phids) - 1) . ')';
             } else {
                 $suffix = null;
             }
             $reviewers = $this->handles[$first]->renderLink() . $suffix;
         } else {
             $reviewers = '<em>None</em>';
         }
         $link = phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle()));
         $rows[] = array('D' . $revision->getID(), $link, phutil_escape_html($status), number_format($revision->getLineCount()), $this->handles[$revision->getAuthorPHID()]->renderLink(), $reviewers, phabricator_datetime($revision->getDateModified(), $user), phabricator_date($revision->getDateCreated(), $user));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('ID', 'Revision', 'Status', 'Lines', 'Author', 'Reviewers', 'Updated', 'Created'));
     $table->setColumnClasses(array(null, 'wide pri', null, 'n', null, null, 'right', 'right'));
     if ($this->noDataString) {
         $table->setNoDataString($this->noDataString);
     }
     return $table->render();
 }
 private function renderHeader(DifferentialRevision $revision)
 {
     $view = id(new PHUIHeaderView())->setHeader($revision->getTitle($revision))->setUser($this->getUser())->setPolicyObject($revision);
     $status = $revision->getStatus();
     $status_name = DifferentialRevisionStatus::renderFullDescription($status);
     $view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
     return $view;
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $query = $request->getValue('query');
     $guids = $request->getValue('guids');
     $results = array();
     if (!$guids) {
         return $results;
     }
     $revisions = id(new DifferentialRevisionListData($query, (array) $guids))->loadRevisions();
     foreach ($revisions as $revision) {
         $diff = $revision->loadActiveDiff();
         if (!$diff) {
             continue;
         }
         $id = $revision->getID();
         $results[] = array('id' => $id, 'phid' => $revision->getPHID(), 'name' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'authorPHID' => $revision->getAuthorPHID(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'sourcePath' => $diff->getSourcePath());
     }
     return $results;
 }
 public function renderValueForRevisionView()
 {
     $revision = $this->getRevision();
     $diff = $this->getDiff();
     $status = $revision->getStatus();
     $next_step = null;
     if ($status == DifferentialRevisionStatus::ACCEPTED) {
         switch ($diff->getSourceControlSystem()) {
             case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                 $next_step = 'arc amend --revision ' . $revision->getID();
                 break;
             case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                 $next_step = 'arc commit --revision ' . $revision->getID();
                 break;
         }
         if ($next_step) {
             $next_step = ' &middot; ' . 'Next step: <tt>' . phutil_escape_html($next_step) . '</tt>';
         }
     }
     $status = DifferentialRevisionStatus::getNameForRevisionStatus($status);
     return '<strong>' . $status . '</strong>' . $next_step;
 }
 /**
  * @task internal
  */
 private function buildWhereClause($conn_r)
 {
     $where = array();
     if ($this->pathIDs) {
         $path_clauses = array();
         $repo_info = igroup($this->pathIDs, 'repositoryID');
         foreach ($repo_info as $repository_id => $paths) {
             $path_clauses[] = qsprintf($conn_r, '(p.repositoryID = %d AND p.pathID IN (%Ld))', $repository_id, ipull($paths, 'pathID'));
         }
         $path_clauses = '(' . implode(' OR ', $path_clauses) . ')';
         $where[] = $path_clauses;
     }
     if ($this->authors) {
         $where[] = qsprintf($conn_r, 'r.authorPHID IN (%Ls)', $this->authors);
     }
     if ($this->revIDs) {
         $where[] = qsprintf($conn_r, 'r.id IN (%Ld)', $this->revIDs);
     }
     if ($this->repositoryPHIDs) {
         $where[] = qsprintf($conn_r, 'r.repositoryPHID IN (%Ls)', $this->repositoryPHIDs);
     }
     if ($this->commitHashes) {
         $hash_clauses = array();
         foreach ($this->commitHashes as $info) {
             list($type, $hash) = $info;
             $hash_clauses[] = qsprintf($conn_r, '(hash_rel.type = %s AND hash_rel.hash = %s)', $type, $hash);
         }
         $hash_clauses = '(' . implode(' OR ', $hash_clauses) . ')';
         $where[] = $hash_clauses;
     }
     if ($this->phids) {
         $where[] = qsprintf($conn_r, 'r.phid IN (%Ls)', $this->phids);
     }
     if ($this->branches) {
         $where[] = qsprintf($conn_r, 'r.branchName in (%Ls)', $this->branches);
     }
     if ($this->arcanistProjectPHIDs) {
         $where[] = qsprintf($conn_r, 'r.arcanistProjectPHID in (%Ls)', $this->arcanistProjectPHIDs);
     }
     switch ($this->status) {
         case self::STATUS_ANY:
             break;
         case self::STATUS_OPEN:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', DifferentialRevisionStatus::getOpenStatuses());
             break;
         case self::STATUS_NEEDS_REVIEW:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW));
             break;
         case self::STATUS_NEEDS_REVISION:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVISION));
             break;
         case self::STATUS_ACCEPTED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::ACCEPTED));
             break;
         case self::STATUS_CLOSED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', DifferentialRevisionStatus::getClosedStatuses());
             break;
         case self::STATUS_ABANDONED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ld)', array(ArcanistDifferentialRevisionStatus::ABANDONED));
             break;
         default:
             throw new Exception("Unknown revision status filter constant '{$this->status}'!");
     }
     $where[] = $this->buildPagingClause($conn_r);
     return $this->formatWhereClause($where);
 }
 public function isClosed()
 {
     return DifferentialRevisionStatus::isClosedStatus($this->getStatus());
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $authors = $request->getValue('authors');
     $ccs = $request->getValue('ccs');
     $reviewers = $request->getValue('reviewers');
     $status = $request->getValue('status');
     $order = $request->getValue('order');
     $commit_hashes = $request->getValue('commitHashes');
     $limit = $request->getValue('limit');
     $offset = $request->getValue('offset');
     $ids = $request->getValue('ids');
     $phids = $request->getValue('phids');
     $subscribers = $request->getValue('subscribers');
     $responsible_users = $request->getValue('responsibleUsers');
     $query = new DifferentialRevisionQuery();
     if ($authors) {
         $query->withAuthors($authors);
     }
     if ($ccs) {
         $query->withCCs($ccs);
     }
     if ($reviewers) {
         $query->withReviewers($reviewers);
     }
     /* TODO: Implement.
         $paths     = $request->getValue('paths');
         if ($paths) {
           foreach ($paths as $path) {
     
             // (Lookup the repository IDs.)
     
             $query->withPath($repository_id, $path);
           }
         }
      */
     if ($commit_hashes) {
         $hash_types = DifferentialRevisionHash::getTypes();
         foreach ($commit_hashes as $info) {
             list($type, $hash) = $info;
             if (empty($type) || !in_array($type, $hash_types) || empty($hash)) {
                 throw new ConduitException('ERR-INVALID-PARAMETER');
             }
         }
         $query->withCommitHashes($commit_hashes);
     }
     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);
     }
     if ($responsible_users) {
         $query->withResponsibleUsers($responsible_users);
     }
     if ($subscribers) {
         $query->withSubscribers($subscribers);
     }
     $query->needRelationships(true);
     $query->needCommitPHIDs(true);
     $query->needDiffIDs(true);
     $query->needActiveDiffs(true);
     $revisions = $query->execute();
     $results = array();
     foreach ($revisions as $revision) {
         $diff = $revision->getActiveDiff();
         if (!$diff) {
             continue;
         }
         $id = $revision->getID();
         $results[] = array('id' => $id, 'phid' => $revision->getPHID(), 'title' => $revision->getTitle(), 'uri' => PhabricatorEnv::getProductionURI('/D' . $id), 'dateCreated' => $revision->getDateCreated(), 'dateModified' => $revision->getDateModified(), 'authorPHID' => $revision->getAuthorPHID(), 'status' => $revision->getStatus(), 'statusName' => DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus()), 'sourcePath' => $diff->getSourcePath(), 'summary' => $revision->getSummary(), 'testPlan' => $revision->getTestPlan(), 'lineCount' => $revision->getLineCount(), 'diffs' => $revision->getDiffIDs(), 'commits' => $revision->getCommitPHIDs(), 'reviewers' => array_values($revision->getReviewers()), 'ccs' => array_values($revision->getCCPHIDs()));
     }
     return $results;
 }
 /**
  * @task internal
  */
 protected function buildWhereClause(AphrontDatabaseConnection $conn_r)
 {
     $where = array();
     if ($this->pathIDs) {
         $path_clauses = array();
         $repo_info = igroup($this->pathIDs, 'repositoryID');
         foreach ($repo_info as $repository_id => $paths) {
             $path_clauses[] = qsprintf($conn_r, '(p.repositoryID = %d AND p.pathID IN (%Ld))', $repository_id, ipull($paths, 'pathID'));
         }
         $path_clauses = '(' . implode(' OR ', $path_clauses) . ')';
         $where[] = $path_clauses;
     }
     if ($this->authors) {
         $where[] = qsprintf($conn_r, 'r.authorPHID IN (%Ls)', $this->authors);
     }
     if ($this->revIDs) {
         $where[] = qsprintf($conn_r, 'r.id IN (%Ld)', $this->revIDs);
     }
     if ($this->repositoryPHIDs) {
         $where[] = qsprintf($conn_r, 'r.repositoryPHID IN (%Ls)', $this->repositoryPHIDs);
     }
     if ($this->commitHashes) {
         $hash_clauses = array();
         foreach ($this->commitHashes as $info) {
             list($type, $hash) = $info;
             $hash_clauses[] = qsprintf($conn_r, '(hash_rel.type = %s AND hash_rel.hash = %s)', $type, $hash);
         }
         $hash_clauses = '(' . implode(' OR ', $hash_clauses) . ')';
         $where[] = $hash_clauses;
     }
     if ($this->commitPHIDs) {
         $where[] = qsprintf($conn_r, 'commits.commitPHID IN (%Ls)', $this->commitPHIDs);
     }
     if ($this->phids) {
         $where[] = qsprintf($conn_r, 'r.phid IN (%Ls)', $this->phids);
     }
     if ($this->branches) {
         $where[] = qsprintf($conn_r, 'r.branchName in (%Ls)', $this->branches);
     }
     if ($this->updatedEpochMin !== null) {
         $where[] = qsprintf($conn_r, 'r.dateModified >= %d', $this->updatedEpochMin);
     }
     if ($this->updatedEpochMax !== null) {
         $where[] = qsprintf($conn_r, 'r.dateModified <= %d', $this->updatedEpochMax);
     }
     // NOTE: Although the status constants are integers in PHP, the column is a
     // string column in MySQL, and MySQL won't use keys on string columns if
     // you put integers in the query.
     switch ($this->status) {
         case self::STATUS_ANY:
             break;
         case self::STATUS_OPEN:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getOpenStatuses());
             break;
         case self::STATUS_NEEDS_REVIEW:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW));
             break;
         case self::STATUS_NEEDS_REVISION:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::NEEDS_REVISION));
             break;
         case self::STATUS_ACCEPTED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::ACCEPTED));
             break;
         case self::STATUS_CLOSED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getClosedStatuses());
             break;
         case self::STATUS_ABANDONED:
             $where[] = qsprintf($conn_r, 'r.status IN (%Ls)', array(ArcanistDifferentialRevisionStatus::ABANDONED));
             break;
         default:
             throw new Exception(pht("Unknown revision status filter constant '%s'!", $this->status));
     }
     $where[] = $this->buildWhereClauseParts($conn_r);
     return $this->formatWhereClause($where);
 }
 private function renderRevisionTable(array $revisions, $header, $nodata, array $handles, array $reviewer_map)
 {
     $rows = array();
     foreach ($revisions as $revision) {
         $status = DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus());
         $reviewers = idx($reviewer_map, $revision->getID(), array());
         if ($reviewers) {
             $first = reset($reviewers);
             if (count($reviewers) > 1) {
                 $suffix = ' (+' . (count($reviewers) - 1) . ')';
             } else {
                 $suffix = null;
             }
             $reviewers = $handles[$first]->renderLink() . $suffix;
         } else {
             $reviewers = '<em>None</em>';
         }
         $rows[] = array('D' . $revision->getID(), '<strong>' . phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle())) . '</strong>', phutil_escape_html($status), number_format($revision->getLineCount()), $handles[$revision->getAuthorPHID()]->renderLink(), $reviewers, phabricator_format_timestamp($revision->getDateModified()), phabricator_format_timestamp($revision->getDateCreated()));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('ID', 'Revision', 'Status', 'Lines', 'Author', 'Reviewers', 'Updated', 'Created'));
     $table->setColumnClasses(array(null, 'wide', null, null, null, null, null, null));
     if ($nodata !== null) {
         $table->setNoDataString($nodata);
     }
     $panel = new AphrontPanelView();
     $panel->setHeader($header);
     $panel->appendChild($table);
     return $panel;
 }
 private function getRevisionProperties(DifferentialRevision $revision, DifferentialDiff $diff, array $handles, array $diff_properties)
 {
     $properties = array();
     $status = $revision->getStatus();
     $next_step = null;
     if ($status == DifferentialRevisionStatus::ACCEPTED) {
         switch ($diff->getSourceControlSystem()) {
             case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                 $next_step = 'arc amend --revision ' . $revision->getID();
                 break;
             case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                 $next_step = 'arc commit --revision ' . $revision->getID();
                 break;
         }
         if ($next_step) {
             $next_step = ' &middot; ' . 'Next step: <tt>' . phutil_escape_html($next_step) . '</tt>';
         }
     }
     $status = DifferentialRevisionStatus::getNameForRevisionStatus($status);
     $properties['Revision Status'] = '<strong>' . $status . '</strong>' . $next_step;
     $author = $handles[$revision->getAuthorPHID()];
     $properties['Author'] = $author->renderLink();
     $properties['Reviewers'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getReviewers()));
     $properties['CCs'] = $this->renderHandleLinkList(array_select_keys($handles, $revision->getCCPHIDs()));
     $host = $diff->getSourceMachine();
     if ($host) {
         $properties['Host'] = phutil_escape_html($host);
     }
     $path = $diff->getSourcePath();
     if ($path) {
         $branch = $diff->getBranch() ? ' (' . $diff->getBranch() . ')' : '';
         $properties['Path'] = phutil_escape_html("{$path} {$branch}");
     }
     $lstar = DifferentialRevisionUpdateHistoryView::renderDiffLintStar($diff);
     $lmsg = DifferentialRevisionUpdateHistoryView::getDiffLintMessage($diff);
     $ldata = idx($diff_properties, 'arc:lint');
     $ltail = null;
     if ($ldata) {
         $ldata = igroup($ldata, 'path');
         $lint_messages = array();
         foreach ($ldata as $path => $messages) {
             $message_markup = array();
             foreach ($messages as $message) {
                 $path = idx($message, 'path');
                 $line = idx($message, 'line');
                 $code = idx($message, 'code');
                 $severity = idx($message, 'severity');
                 $name = idx($message, 'name');
                 $description = idx($message, 'description');
                 $message_markup[] = '<li>' . '<span class="lint-severity-' . phutil_escape_html($severity) . '">' . phutil_escape_html(ucwords($severity)) . '</span>' . ' ' . '(' . phutil_escape_html($code) . ') ' . phutil_escape_html($name) . ' at line ' . phutil_escape_html($line) . '<p>' . phutil_escape_html($description) . '</p>' . '</li>';
             }
             $lint_messages[] = '<li class="lint-file-block">' . 'Lint for <strong>' . phutil_escape_html($path) . '</strong>' . '<ul>' . implode("\n", $message_markup) . '</ul>' . '</li>';
         }
         $ltail = '<div class="differential-lint-block">' . '<ul>' . implode("\n", $lint_messages) . '</ul>' . '</div>';
     }
     $properties['Lint'] = $lstar . ' ' . $lmsg . $ltail;
     $ustar = DifferentialRevisionUpdateHistoryView::renderDiffUnitStar($diff);
     $umsg = DifferentialRevisionUpdateHistoryView::getDiffUnitMessage($diff);
     $postponed_count = 0;
     $udata = idx($diff_properties, 'arc:unit');
     $utail = null;
     if ($udata) {
         $unit_messages = array();
         foreach ($udata as $test) {
             $name = phutil_escape_html(idx($test, 'name'));
             $result = phutil_escape_html(idx($test, 'result'));
             if ($result != DifferentialUnitTestResult::RESULT_POSTPONED && $result != DifferentialUnitTestResult::RESULT_PASS) {
                 $userdata = phutil_escape_html(idx($test, 'userdata'));
                 if (strlen($userdata) > 256) {
                     $userdata = substr($userdata, 0, 256) . '...';
                 }
                 $userdata = str_replace("\n", '<br />', $userdata);
                 $unit_messages[] = '<tr>' . '<th>' . $name . '</th>' . '<th class="unit-test-result">' . '<div class="result-' . $result . '">' . strtoupper($result) . '</div>' . '</th>' . '<td>' . $userdata . '</td>' . '</tr>';
                 $utail = '<div class="differential-unit-block">' . '<table class="differential-unit-table">' . implode("\n", $unit_messages) . '</table>' . '</div>';
             } else {
                 if ($result == DifferentialUnitTestResult::RESULT_POSTPONED) {
                     $postponed_count++;
                 }
             }
         }
     }
     if ($postponed_count > 0 && $diff->getUnitStatus() == DifferentialUnitStatus::UNIT_POSTPONED) {
         $umsg = $postponed_count . ' ' . $umsg;
     }
     $properties['Unit'] = $ustar . ' ' . $umsg . $utail;
     if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) {
         $tasks = $revision->getAttachedPHIDs(PhabricatorPHIDConstants::PHID_TYPE_TASK);
         if ($tasks) {
             $links = array();
             foreach ($tasks as $task_phid) {
                 $links[] = $handles[$task_phid]->renderLink();
             }
             $properties['Maniphest Tasks'] = implode('<br />', $links);
         }
     }
     $commit_phids = $revision->getCommitPHIDs();
     if ($commit_phids) {
         $links = array();
         foreach ($commit_phids as $commit_phid) {
             $links[] = $handles[$commit_phid]->renderLink();
         }
         $properties['Commits'] = implode('<br />', $links);
     }
     $properties['Lines'] = number_format($diff->getLineCount());
     $arcanist_phid = $diff->getArcanistProjectPHID();
     if ($arcanist_phid) {
         $properties['Arcanist Project'] = phutil_escape_html($handles[$arcanist_phid]->getName());
     }
     $properties['Apply Patch'] = '<tt>arc patch D' . $revision->getID() . '</tt>';
     $properties['Export Patch'] = '<tt>arc export --revision ' . $revision->getID() . '</tt>';
     return $properties;
 }