private function renderAuditStatusView(array $audit_requests)
 {
     assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
     $viewer = $this->getViewer();
     $authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
     $view = new PHUIStatusListView();
     foreach ($audit_requests as $request) {
         $code = $request->getAuditStatus();
         $item = new PHUIStatusItemView();
         $item->setIcon(PhabricatorAuditStatusConstants::getStatusIcon($code), PhabricatorAuditStatusConstants::getStatusColor($code), PhabricatorAuditStatusConstants::getStatusName($code));
         $note = array();
         foreach ($request->getAuditReasons() as $reason) {
             $note[] = phutil_tag('div', array(), $reason);
         }
         $item->setNote($note);
         $auditor_phid = $request->getAuditorPHID();
         $target = $viewer->renderHandle($auditor_phid);
         $item->setTarget($target);
         if (isset($authority_map[$auditor_phid])) {
             $item->setHighlighted(true);
         }
         $view->addItem($item);
     }
     return $view;
 }
 public function render()
 {
     $user = $this->user;
     $authority = array_fill_keys($this->authorityPHIDs, true);
     $rowc = array();
     $last = null;
     $rows = array();
     foreach ($this->audits as $audit) {
         $commit_phid = $audit->getCommitPHID();
         if ($last == $commit_phid) {
             $commit_name = null;
             $commit_desc = null;
         } else {
             $commit_name = $this->getHandle($commit_phid)->renderLink();
             $commit_desc = $this->getCommitDescription($commit_phid);
             $last = $commit_phid;
         }
         $reasons = $audit->getAuditReasons();
         foreach ($reasons as $key => $reason) {
             $reasons[$key] = phutil_escape_html($reason);
         }
         $reasons = implode('<br />', $reasons);
         $status_code = $audit->getAuditStatus();
         $status = PhabricatorAuditStatusConstants::getStatusName($status_code);
         $auditor_handle = $this->getHandle($audit->getAuditorPHID());
         $rows[] = array($commit_name, phutil_escape_html($commit_desc), $auditor_handle->renderLink(), phutil_escape_html($status), $reasons);
         $row_class = null;
         $has_authority = !empty($authority[$audit->getAuditorPHID()]);
         if ($has_authority) {
             $commit_author = $this->commits[$commit_phid]->getAuthorPHID();
             // You don't have authority over package and project audits on your own
             // commits.
             $auditor_is_user = $audit->getAuditorPHID() == $user->getPHID();
             $user_is_author = $commit_author == $user->getPHID();
             if ($auditor_is_user || !$user_is_author) {
                 $row_class = 'highlighted';
             }
         }
         $rowc[] = $row_class;
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('Commit', 'Description', 'Auditor', 'Status', 'Details'));
     $table->setColumnClasses(array('pri', $this->showDescriptions ? 'wide' : '', '', '', $this->showDescriptions ? '' : 'wide'));
     $table->setRowClasses($rowc);
     $table->setColumnVisibility(array($this->showDescriptions, $this->showDescriptions, true, true, true));
     if ($this->noDataString) {
         $table->setNoDataString($this->noDataString);
     }
     return $table->render();
 }
 public function execute(PhutilArgumentParser $args)
 {
     $viewer = $this->getViewer();
     $users = $this->loadUsers($args->getArg('users'));
     $repos = $this->loadRepos($args->getArg('repositories'));
     $commits = $this->loadCommits($args->getArg('commits'));
     $ids = $this->parseList($args->getArg('ids'));
     $status = $args->getArg('status');
     if (!$status) {
         $status = DiffusionCommitQuery::AUDIT_STATUS_OPEN;
     }
     $min_date = $this->loadDate($args->getArg('min-commit-date'));
     $max_date = $this->loadDate($args->getArg('max-commit-date'));
     if ($min_date && $max_date && $min_date > $max_date) {
         throw new PhutilArgumentUsageException('Specified max date must come after specified min date.');
     }
     $is_dry_run = $args->getArg('dry-run');
     $query = id(new DiffusionCommitQuery())->setViewer($this->getViewer())->needAuditRequests(true);
     if ($status) {
         $query->withAuditStatus($status);
     }
     $id_map = array();
     if ($ids) {
         $id_map = array_fuse($ids);
         $query->withAuditIDs($ids);
     }
     if ($repos) {
         $query->withRepositoryIDs(mpull($repos, 'getID'));
     }
     $auditor_map = array();
     if ($users) {
         $auditor_map = array_fuse(mpull($users, 'getPHID'));
         $query->withAuditorPHIDs($auditor_map);
     }
     if ($commits) {
         $query->withPHIDs(mpull($commits, 'getPHID'));
     }
     $commits = $query->execute();
     $commits = mpull($commits, null, 'getPHID');
     $audits = array();
     foreach ($commits as $commit) {
         $commit_audits = $commit->getAudits();
         foreach ($commit_audits as $key => $audit) {
             if ($id_map && empty($id_map[$audit->getID()])) {
                 unset($commit_audits[$key]);
                 continue;
             }
             if ($auditor_map && empty($auditor_map[$audit->getAuditorPHID()])) {
                 unset($commit_audits[$key]);
                 continue;
             }
             if ($min_date && $commit->getEpoch() < $min_date) {
                 unset($commit_audits[$key]);
                 continue;
             }
             if ($max_date && $commit->getEpoch() > $max_date) {
                 unset($commit_audits[$key]);
                 continue;
             }
         }
         $audits[] = $commit_audits;
     }
     $audits = array_mergev($audits);
     $console = PhutilConsole::getConsole();
     if (!$audits) {
         $console->writeErr("%s\n", pht('No audits match the query.'));
         return 0;
     }
     $handles = id(new PhabricatorHandleQuery())->setViewer($this->getViewer())->withPHIDs(mpull($audits, 'getAuditorPHID'))->execute();
     foreach ($audits as $audit) {
         $commit = $commits[$audit->getCommitPHID()];
         $console->writeOut("%s\n", sprintf('%10d %-16s %-16s %s: %s', $audit->getID(), $handles[$audit->getAuditorPHID()]->getName(), PhabricatorAuditStatusConstants::getStatusName($audit->getAuditStatus()), $commit->getRepository()->formatCommitName($commit->getCommitIdentifier()), trim($commit->getSummary())));
     }
     if (!$is_dry_run) {
         $message = pht('Really delete these %d audit(s)? They will be permanently deleted ' . 'and can not be recovered.', count($audits));
         if ($console->confirm($message)) {
             foreach ($audits as $audit) {
                 $id = $audit->getID();
                 $console->writeOut("%s\n", pht('Deleting audit %d...', $id));
                 $audit->delete();
             }
         }
     }
     return 0;
 }
 public function buildList()
 {
     $user = $this->getUser();
     if (!$user) {
         throw new Exception(pht('You must %s before %s!', 'setUser()', __FUNCTION__ . '()'));
     }
     $rowc = array();
     $list = new PHUIObjectItemListView();
     foreach ($this->commits as $commit) {
         $commit_phid = $commit->getPHID();
         $commit_handle = $this->getHandle($commit_phid);
         $committed = null;
         $commit_name = $commit_handle->getName();
         $commit_link = $commit_handle->getURI();
         $commit_desc = $this->getCommitDescription($commit_phid);
         $committed = phabricator_datetime($commit->getEpoch(), $user);
         $audits = mpull($commit->getAudits(), null, 'getAuditorPHID');
         $auditors = array();
         $reasons = array();
         foreach ($audits as $audit) {
             $auditor_phid = $audit->getAuditorPHID();
             $auditors[$auditor_phid] = $this->getHandle($auditor_phid)->renderLink();
         }
         $auditors = phutil_implode_html(', ', $auditors);
         $authority_audits = array_select_keys($audits, $this->authorityPHIDs);
         if ($authority_audits) {
             $audit = reset($authority_audits);
         } else {
             $audit = reset($audits);
         }
         if ($audit) {
             $reasons = $audit->getAuditReasons();
             $reasons = phutil_implode_html(', ', $reasons);
             $status_code = $audit->getAuditStatus();
             $status_text = PhabricatorAuditStatusConstants::getStatusName($status_code);
             $status_color = PhabricatorAuditStatusConstants::getStatusColor($status_code);
             $status_icon = PhabricatorAuditStatusConstants::getStatusIcon($status_code);
         } else {
             $reasons = null;
             $status_text = null;
             $status_color = null;
             $status_icon = null;
         }
         $author_phid = $commit->getAuthorPHID();
         if ($author_phid) {
             $author_name = $this->getHandle($author_phid)->renderLink();
         } else {
             $author_name = $commit->getCommitData()->getAuthorName();
         }
         $item = id(new PHUIObjectItemView())->setObjectName($commit_name)->setHeader($commit_desc)->setHref($commit_link)->addAttribute(pht('Author: %s', $author_name))->addAttribute($reasons)->addIcon('none', $committed);
         if (!empty($auditors)) {
             $item->addByLine(pht('Auditors: %s', $auditors));
         }
         if ($status_color) {
             $item->setStatusIcon($status_icon . ' ' . $status_color, $status_text);
         }
         $list->addItem($item);
     }
     if ($this->noDataString) {
         $list->setNoDataString($this->noDataString);
     }
     return $list;
 }
 protected function buildWhereClause(AphrontDatabaseConnection $conn_r)
 {
     $where = array();
     if ($this->repositoryPHIDs !== null) {
         $map_repositories = id(new PhabricatorRepositoryQuery())->setViewer($this->getViewer())->withPHIDs($this->repositoryPHIDs)->execute();
         if (!$map_repositories) {
             throw new PhabricatorEmptyQueryException();
         }
         $repository_ids = mpull($map_repositories, 'getID');
         if ($this->repositoryIDs !== null) {
             $repository_ids = array_merge($repository_ids, $this->repositoryIDs);
         }
         $this->withRepositoryIDs($repository_ids);
     }
     if ($this->ids !== null) {
         $where[] = qsprintf($conn_r, 'commit.id IN (%Ld)', $this->ids);
     }
     if ($this->phids !== null) {
         $where[] = qsprintf($conn_r, 'commit.phid IN (%Ls)', $this->phids);
     }
     if ($this->repositoryIDs !== null) {
         $where[] = qsprintf($conn_r, 'commit.repositoryID IN (%Ld)', $this->repositoryIDs);
     }
     if ($this->authorPHIDs !== null) {
         $where[] = qsprintf($conn_r, 'commit.authorPHID IN (%Ls)', $this->authorPHIDs);
     }
     if ($this->epochMin !== null) {
         $where[] = qsprintf($conn_r, 'commit.epoch >= %d', $this->epochMin);
     }
     if ($this->epochMax !== null) {
         $where[] = qsprintf($conn_r, 'commit.epoch <= %d', $this->epochMax);
     }
     if ($this->importing !== null) {
         if ($this->importing) {
             $where[] = qsprintf($conn_r, '(commit.importStatus & %d) != %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL);
         } else {
             $where[] = qsprintf($conn_r, '(commit.importStatus & %d) = %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL);
         }
     }
     if ($this->identifiers !== null) {
         $min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
         $min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
         $refs = array();
         $bare = array();
         foreach ($this->identifiers as $identifier) {
             $matches = null;
             preg_match('/^(?:[rR]([A-Z]+:?|[0-9]+:))?(.*)$/', $identifier, $matches);
             $repo = nonempty(rtrim($matches[1], ':'), null);
             $commit_identifier = nonempty($matches[2], null);
             if ($repo === null) {
                 if ($this->defaultRepository) {
                     $repo = $this->defaultRepository->getCallsign();
                 }
             }
             if ($repo === null) {
                 if (strlen($commit_identifier) < $min_unqualified) {
                     continue;
                 }
                 $bare[] = $commit_identifier;
             } else {
                 $refs[] = array('callsign' => $repo, 'identifier' => $commit_identifier);
             }
         }
         $sql = array();
         foreach ($bare as $identifier) {
             $sql[] = qsprintf($conn_r, '(commit.commitIdentifier LIKE %> AND ' . 'LENGTH(commit.commitIdentifier) = 40)', $identifier);
         }
         if ($refs) {
             $callsigns = ipull($refs, 'callsign');
             $repos = id(new PhabricatorRepositoryQuery())->setViewer($this->getViewer())->withIdentifiers($callsigns);
             $repos->execute();
             $repos = $repos->getIdentifierMap();
             foreach ($refs as $key => $ref) {
                 $repo = idx($repos, $ref['callsign']);
                 if (!$repo) {
                     continue;
                 }
                 if ($repo->isSVN()) {
                     if (!ctype_digit($ref['identifier'])) {
                         continue;
                     }
                     $sql[] = qsprintf($conn_r, '(commit.repositoryID = %d AND commit.commitIdentifier = %s)', $repo->getID(), (int) $ref['identifier']);
                 } else {
                     if (strlen($ref['identifier']) < $min_qualified) {
                         continue;
                     }
                     $sql[] = qsprintf($conn_r, '(commit.repositoryID = %d AND commit.commitIdentifier LIKE %>)', $repo->getID(), $ref['identifier']);
                 }
             }
         }
         if (!$sql) {
             // If we discarded all possible identifiers (e.g., they all referenced
             // bogus repositories or were all too short), make sure the query finds
             // nothing.
             throw new PhabricatorEmptyQueryException(pht('No commit identifiers.'));
         }
         $where[] = '(' . implode(' OR ', $sql) . ')';
     }
     if ($this->auditIDs !== null) {
         $where[] = qsprintf($conn_r, 'audit.id IN (%Ld)', $this->auditIDs);
     }
     if ($this->auditorPHIDs !== null) {
         $where[] = qsprintf($conn_r, 'audit.auditorPHID IN (%Ls)', $this->auditorPHIDs);
     }
     if ($this->auditAwaitingUser) {
         $awaiting_user_phid = $this->auditAwaitingUser->getPHID();
         // Exclude package and project audits associated with commits where
         // the user is the author.
         $where[] = qsprintf($conn_r, '(commit.authorPHID IS NULL OR commit.authorPHID != %s)
       OR (audit.auditorPHID = %s)', $awaiting_user_phid, $awaiting_user_phid);
     }
     $status = $this->auditStatus;
     if ($status !== null) {
         switch ($status) {
             case self::AUDIT_STATUS_PARTIAL:
                 $where[] = qsprintf($conn_r, 'commit.auditStatus = %d', PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED);
                 break;
             case self::AUDIT_STATUS_ACCEPTED:
                 $where[] = qsprintf($conn_r, 'commit.auditStatus = %d', PhabricatorAuditCommitStatusConstants::FULLY_AUDITED);
                 break;
             case self::AUDIT_STATUS_CONCERN:
                 $where[] = qsprintf($conn_r, 'audit.auditStatus = %s', PhabricatorAuditStatusConstants::CONCERNED);
                 break;
             case self::AUDIT_STATUS_OPEN:
                 $where[] = qsprintf($conn_r, 'audit.auditStatus in (%Ls)', PhabricatorAuditStatusConstants::getOpenStatusConstants());
                 if ($this->auditAwaitingUser) {
                     $where[] = qsprintf($conn_r, 'awaiting.auditStatus IS NULL OR awaiting.auditStatus != %s', PhabricatorAuditStatusConstants::RESIGNED);
                 }
                 break;
             case self::AUDIT_STATUS_ANY:
                 break;
             default:
                 $valid = array(self::AUDIT_STATUS_ANY, self::AUDIT_STATUS_OPEN, self::AUDIT_STATUS_CONCERN, self::AUDIT_STATUS_ACCEPTED, self::AUDIT_STATUS_PARTIAL);
                 throw new Exception(pht("Unknown audit status '%s'! Valid statuses are: %s.", $status, implode(', ', $valid)));
         }
     }
     $where[] = $this->buildPagingClause($conn_r);
     return $this->formatWhereClause($where);
 }
 public function render()
 {
     $rowc = array();
     $last = null;
     $rows = array();
     foreach ($this->audits as $audit) {
         $commit_phid = $audit->getCommitPHID();
         $committed = null;
         if ($last == $commit_phid) {
             $commit_name = null;
             $commit_desc = null;
         } else {
             $commit_name = $this->getHandle($commit_phid)->renderLink();
             $commit_desc = $this->getCommitDescription($commit_phid);
             $commit = idx($this->commits, $commit_phid);
             if ($commit && $this->user) {
                 $committed = phabricator_datetime($commit->getEpoch(), $this->user);
             }
             $last = $commit_phid;
         }
         $reasons = $audit->getAuditReasons();
         foreach ($reasons as $key => $reason) {
             $reasons[$key] = phutil_escape_html($reason);
         }
         $reasons = implode('<br />', $reasons);
         $status_code = $audit->getAuditStatus();
         $status = PhabricatorAuditStatusConstants::getStatusName($status_code);
         $auditor_handle = $this->getHandle($audit->getAuditorPHID());
         $rows[] = array($commit_name, phutil_escape_html($commit_desc), $committed, $auditor_handle->renderLink(), phutil_escape_html($status), $reasons);
         $row_class = null;
         if (array_key_exists($audit->getID(), $this->getHighlightedAudits())) {
             $row_class = 'highlighted';
         }
         $rowc[] = $row_class;
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('Commit', 'Description', 'Committed', 'Auditor', 'Status', 'Details'));
     $table->setColumnClasses(array('pri', $this->showDescriptions ? 'wide' : '', '', '', '', $this->showDescriptions ? '' : 'wide'));
     $table->setRowClasses($rowc);
     $table->setColumnVisibility(array($this->showDescriptions, $this->showDescriptions, $this->showDescriptions, true, true, true));
     if ($this->noDataString) {
         $table->setNoDataString($this->noDataString);
     }
     return $table->render();
 }
 public function processRequest()
 {
     $this->request = $this->getRequest();
     $this->user = $this->request->getUser();
     $this->commitPHID = $this->request->getStr('c-phid');
     $this->packagePHID = $this->request->getStr('p-phid');
     $relationship = id(new PhabricatorOwnersPackageCommitRelationship())->loadOneWhere('commitPHID = %s AND packagePHID=%s', $this->commitPHID, $this->packagePHID);
     if (!$relationship) {
         return new Aphront404Response();
     }
     $package = id(new PhabricatorOwnersPackage())->loadOneWhere("phid = %s", $this->packagePHID);
     $owners = id(new PhabricatorOwnersOwner())->loadAllWhere('packageID = %d', $package->getID());
     $owners_phids = mpull($owners, 'getUserPHID');
     if (!$this->user->getIsAdmin() && !in_array($this->user->getPHID(), $owners_phids)) {
         return $this->buildStandardPageResponse(id(new AphrontErrorView())->setSeverity(AphrontErrorView::SEVERITY_ERROR)->setTitle("Only admin or owner of the package can audit the " . "commit."), array('title' => 'Audit a Commit'));
     }
     if ($this->request->isFormPost()) {
         return $this->saveAuditComments();
     }
     $package_link = phutil_render_tag('a', array('href' => '/owners/package/' . $package->getID() . '/'), phutil_escape_html($package->getName()));
     $phids = array($this->commitPHID);
     $loader = new PhabricatorObjectHandleData($phids);
     $handles = $loader->loadHandles();
     $objects = $loader->loadObjects();
     $commit_handle = $handles[$this->commitPHID];
     $commit_object = $objects[$this->commitPHID];
     $commit_data = $commit_object->getCommitData();
     $commit_epoch = $commit_handle->getTimeStamp();
     $commit_datetime = phabricator_datetime($commit_epoch, $this->user);
     $commit_link = $this->renderHandleLink($commit_handle);
     $revision_author_phid = null;
     $revision_reviewedby_phid = null;
     $revision_link = null;
     $revision_id = $commit_data->getCommitDetail('differential.revisionID');
     if ($revision_id) {
         $revision = id(new DifferentialRevision())->load($revision_id);
         if ($revision) {
             $revision->loadRelationships();
             $revision_author_phid = $revision->getAuthorPHID();
             $revision_reviewedby_phid = $revision->loadReviewedBy();
             $revision_link = phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle()));
         }
     }
     $commit_author_phid = $commit_data->getCommitDetail('authorPHID');
     $commit_reviewedby_phid = $commit_data->getCommitDetail('reviewerPHID');
     $conn_r = id(new PhabricatorAuditComment())->establishConnection('r');
     $latest_comment = queryfx_one($conn_r, 'SELECT * FROM %T
     WHERE targetPHID = %s and actorPHID in (%Ls)
     ORDER BY ID DESC LIMIT 1', id(new PhabricatorAuditComment())->getTableName(), $this->commitPHID, $owners_phids);
     $auditor_phid = $latest_comment['actorPHID'];
     $user_phids = array_unique(array_filter(array($revision_author_phid, $revision_reviewedby_phid, $commit_author_phid, $commit_reviewedby_phid, $auditor_phid)));
     $user_loader = new PhabricatorObjectHandleData($user_phids);
     $user_handles = $user_loader->loadHandles();
     if ($commit_author_phid && isset($handles[$commit_author_phid])) {
         $commit_author_link = $handles[$commit_author_phid]->renderLink();
     } else {
         $commit_author_link = phutil_escape_html($commit_data->getAuthorName());
     }
     $reasons = $relationship->getAuditReasons();
     $reasons = array_map('phutil_escape_html', $reasons);
     $reasons = implode($reasons, '<br>');
     $latest_comment_content = id(new AphrontFormTextAreaControl())->setLabel('Audit comments')->setName('latest_comments')->setReadOnly(true)->setValue($latest_comment['content']);
     $latest_comment_epoch = $latest_comment['dateModified'];
     $latest_comment_datetime = phabricator_datetime($latest_comment_epoch, $this->user);
     $select = id(new AphrontFormSelectControl())->setLabel('Audit it')->setName('action')->setValue(PhabricatorAuditActionConstants::ACCEPT)->setOptions(PhabricatorAuditActionConstants::getActionNameMap());
     $comment = id(new AphrontFormTextAreaControl())->setLabel('Audit comments')->setName('comments')->setCaption("Explain the audit.");
     $submit = id(new AphrontFormSubmitControl())->setValue('Save')->addCancelButton('/owners/related/view/audit/?phid=' . $this->packagePHID);
     $form = id(new AphrontFormView())->setUser($this->user)->appendChild(id(new AphrontFormMarkupControl())->setLabel('Package')->setValue($package_link))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Commit')->setValue($commit_link))->appendChild(new AphrontFormDividerControl())->appendChild(id(new AphrontFormStaticControl())->setLabel('Commit Summary')->setValue(phutil_escape_html($commit_data->getSummary())))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Commit Author')->setValue($commit_author_link))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Commit Reviewed By')->setValue($this->renderHandleLink(idx($user_handles, $commit_reviewedby_phid))))->appendChild(id(new AphrontFormStaticControl())->setLabel('Commit Time')->setValue($commit_datetime))->appendChild(new AphrontFormDividerControl())->appendChild(id(new AphrontFormMarkupControl())->setLabel('Revision')->setValue($revision_link))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Revision Author')->setValue($this->renderHandleLink(idx($user_handles, $revision_author_phid))))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Revision Reviewed By')->setValue($this->renderHandleLink(idx($user_handles, $revision_reviewedby_phid))))->appendChild(new AphrontFormDividerControl())->appendChild(id(new AphrontFormMarkupControl())->setLabel('Audit Reasons')->setValue($reasons))->appendChild(id(new AphrontFormMarkupControl())->setLabel('Latest Auditor')->setValue($this->renderHandleLink(idx($user_handles, $auditor_phid))))->appendChild(id(new AphrontFormStaticControl())->setLabel('Latest Audit Status')->setValue(idx(PhabricatorAuditStatusConstants::getStatusNameMap(), $relationship->getAuditStatus())))->appendChild(id(new AphrontFormStaticControl())->setLabel('Latest Audit Time')->setValue($latest_comment_datetime))->appendChild($latest_comment_content)->appendChild(new AphrontFormDividerControl())->appendChild($select)->appendChild($comment)->appendChild($submit);
     $panel = id(new AphrontPanelView())->setHeader('Audit a Commit')->setWidth(AphrontPanelView::WIDTH_WIDE)->appendChild($form);
     return $this->buildStandardPageResponse($panel, array('title' => 'Audit a Commit'));
 }
 private function renderCommitTable($data, PhabricatorOwnersPackage $package)
 {
     $commit_phids = array_keys($data);
     $loader = new PhabricatorObjectHandleData($commit_phids);
     $handles = $loader->loadHandles();
     $objects = $loader->loadObjects();
     $owners = id(new PhabricatorOwnersOwner())->loadAllWhere('packageID = %d', $package->getID());
     $owners_phids = mpull($owners, 'getUserPHID');
     if ($this->user->getIsAdmin() || in_array($this->user->getPHID(), $owners_phids)) {
         $allowed_to_audit = true;
     } else {
         $allowed_to_audit = false;
     }
     $rows = array();
     foreach ($commit_phids as $commit_phid) {
         $handle = $handles[$commit_phid];
         $object = $objects[$commit_phid];
         $commit_data = $object->getCommitData();
         $epoch = $handle->getTimeStamp();
         $date = phabricator_date($epoch, $this->user);
         $time = phabricator_time($epoch, $this->user);
         $link = phutil_render_tag('a', array('href' => $handle->getURI()), phutil_escape_html($handle->getName()));
         $row = array($link, $date, $time, phutil_escape_html($commit_data->getSummary()));
         if ($this->view === 'audit') {
             $relationship = $data[$commit_phid];
             $status_link = phutil_escape_html(idx(PhabricatorAuditStatusConstants::getStatusNameMap(), $relationship['auditStatus']));
             if ($allowed_to_audit) {
                 $status_link = phutil_render_tag('a', array('href' => sprintf('/audit/edit/?c-phid=%s&p-phid=%s', idx($relationship, 'commitPHID'), $this->packagePHID)), $status_link);
             }
             $reasons = json_decode($relationship['auditReasons'], true);
             $reasons = array_map('phutil_escape_html', $reasons);
             $reasons = implode($reasons, '<br>');
             $row = array_merge($row, array($status_link, $reasons));
         }
         $rows[] = $row;
     }
     $commit_table = new AphrontTableView($rows);
     $headers = array('Commit', 'Date', 'Time', 'Summary');
     if ($this->view === 'audit') {
         $headers = array_merge($headers, array('Audit Status', 'Audit Reasons'));
     }
     $commit_table->setHeaders($headers);
     $column_classes = array('', '', 'right', 'wide');
     if ($this->view === 'audit') {
         $column_classes = array_merge($column_classes, array('', ''));
     }
     $commit_table->setColumnClasses($column_classes);
     $list_panel = new AphrontPanelView();
     $list_panel->setHeader('Commits Related to package "' . phutil_render_tag('a', array('href' => '/owners/package/' . $package->getID() . '/'), phutil_escape_html($package->getName())) . '"' . ($this->view === 'audit' ? ' and need attention' : ''));
     $list_panel->appendChild($commit_table);
     return $list_panel;
 }
 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn)
 {
     $where = parent::buildWhereClauseParts($conn);
     if ($this->repositoryPHIDs !== null) {
         $map_repositories = id(new PhabricatorRepositoryQuery())->setViewer($this->getViewer())->withPHIDs($this->repositoryPHIDs)->execute();
         if (!$map_repositories) {
             throw new PhabricatorEmptyQueryException();
         }
         $repository_ids = mpull($map_repositories, 'getID');
         if ($this->repositoryIDs !== null) {
             $repository_ids = array_merge($repository_ids, $this->repositoryIDs);
         }
         $this->withRepositoryIDs($repository_ids);
     }
     if ($this->ids !== null) {
         $where[] = qsprintf($conn, 'commit.id IN (%Ld)', $this->ids);
     }
     if ($this->phids !== null) {
         $where[] = qsprintf($conn, 'commit.phid IN (%Ls)', $this->phids);
     }
     if ($this->repositoryIDs !== null) {
         $where[] = qsprintf($conn, 'commit.repositoryID IN (%Ld)', $this->repositoryIDs);
     }
     if ($this->authorPHIDs !== null) {
         $where[] = qsprintf($conn, 'commit.authorPHID IN (%Ls)', $this->authorPHIDs);
     }
     if ($this->epochMin !== null) {
         $where[] = qsprintf($conn, 'commit.epoch >= %d', $this->epochMin);
     }
     if ($this->epochMax !== null) {
         $where[] = qsprintf($conn, 'commit.epoch <= %d', $this->epochMax);
     }
     if ($this->importing !== null) {
         if ($this->importing) {
             $where[] = qsprintf($conn, '(commit.importStatus & %d) != %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL);
         } else {
             $where[] = qsprintf($conn, '(commit.importStatus & %d) = %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL);
         }
     }
     if ($this->identifiers !== null) {
         $min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
         $min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
         $refs = array();
         $bare = array();
         foreach ($this->identifiers as $identifier) {
             $matches = null;
             preg_match('/^(?:[rR]([A-Z]+:?|[0-9]+:))?(.*)$/', $identifier, $matches);
             $repo = nonempty(rtrim($matches[1], ':'), null);
             $commit_identifier = nonempty($matches[2], null);
             if ($repo === null) {
                 if ($this->defaultRepository) {
                     $repo = $this->defaultRepository->getPHID();
                 }
             }
             if ($repo === null) {
                 if (strlen($commit_identifier) < $min_unqualified) {
                     continue;
                 }
                 $bare[] = $commit_identifier;
             } else {
                 $refs[] = array('repository' => $repo, 'identifier' => $commit_identifier);
             }
         }
         $sql = array();
         foreach ($bare as $identifier) {
             $sql[] = qsprintf($conn, '(commit.commitIdentifier LIKE %> AND ' . 'LENGTH(commit.commitIdentifier) = 40)', $identifier);
         }
         if ($refs) {
             $repositories = ipull($refs, 'repository');
             $repos = id(new PhabricatorRepositoryQuery())->setViewer($this->getViewer())->withIdentifiers($repositories);
             $repos->execute();
             $repos = $repos->getIdentifierMap();
             foreach ($refs as $key => $ref) {
                 $repo = idx($repos, $ref['repository']);
                 if (!$repo) {
                     continue;
                 }
                 if ($repo->isSVN()) {
                     if (!ctype_digit((string) $ref['identifier'])) {
                         continue;
                     }
                     $sql[] = qsprintf($conn, '(commit.repositoryID = %d AND commit.commitIdentifier = %s)', $repo->getID(), (int) $ref['identifier']);
                 } else {
                     if (strlen($ref['identifier']) < $min_qualified) {
                         continue;
                     }
                     $identifier = $ref['identifier'];
                     if (strlen($identifier) == 40) {
                         // MySQL seems to do slightly better with this version if the
                         // clause, so issue it if we have a full commit hash.
                         $sql[] = qsprintf($conn, '(commit.repositoryID = %d
               AND commit.commitIdentifier = %s)', $repo->getID(), $identifier);
                     } else {
                         $sql[] = qsprintf($conn, '(commit.repositoryID = %d
               AND commit.commitIdentifier LIKE %>)', $repo->getID(), $identifier);
                     }
                 }
             }
         }
         if (!$sql) {
             // If we discarded all possible identifiers (e.g., they all referenced
             // bogus repositories or were all too short), make sure the query finds
             // nothing.
             throw new PhabricatorEmptyQueryException(pht('No commit identifiers.'));
         }
         $where[] = '(' . implode(' OR ', $sql) . ')';
     }
     if ($this->auditIDs !== null) {
         $where[] = qsprintf($conn, 'audit.id IN (%Ld)', $this->auditIDs);
     }
     if ($this->auditorPHIDs !== null) {
         $where[] = qsprintf($conn, 'audit.auditorPHID IN (%Ls)', $this->auditorPHIDs);
     }
     if ($this->needsAuditByPHIDs !== null) {
         $where[] = qsprintf($conn, 'needs.auditorPHID IN (%Ls)', $this->needsAuditByPHIDs);
     }
     $status = $this->auditStatus;
     if ($status !== null) {
         switch ($status) {
             case self::AUDIT_STATUS_PARTIAL:
                 $where[] = qsprintf($conn, 'commit.auditStatus = %d', PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED);
                 break;
             case self::AUDIT_STATUS_ACCEPTED:
                 $where[] = qsprintf($conn, 'commit.auditStatus = %d', PhabricatorAuditCommitStatusConstants::FULLY_AUDITED);
                 break;
             case self::AUDIT_STATUS_CONCERN:
                 $where[] = qsprintf($conn, 'status.auditStatus = %s', PhabricatorAuditStatusConstants::CONCERNED);
                 break;
             case self::AUDIT_STATUS_OPEN:
                 $where[] = qsprintf($conn, 'status.auditStatus in (%Ls)', PhabricatorAuditStatusConstants::getOpenStatusConstants());
                 break;
             case self::AUDIT_STATUS_ANY:
                 break;
             default:
                 $valid = array(self::AUDIT_STATUS_ANY, self::AUDIT_STATUS_OPEN, self::AUDIT_STATUS_CONCERN, self::AUDIT_STATUS_ACCEPTED, self::AUDIT_STATUS_PARTIAL);
                 throw new Exception(pht("Unknown audit status '%s'! Valid statuses are: %s.", $status, implode(', ', $valid)));
         }
     }
     return $where;
 }
 private function buildWhereClause($conn_r)
 {
     $where = array();
     if ($this->commitPHIDs) {
         $where[] = qsprintf($conn_r, 'req.commitPHID IN (%Ls)', $this->commitPHIDs);
     }
     if ($this->auditorPHIDs) {
         $where[] = qsprintf($conn_r, 'req.auditorPHID IN (%Ls)', $this->auditorPHIDs);
     }
     if ($this->awaitingUser) {
         // Exclude package and project audits associated with commits where
         // the user is the author.
         $where[] = qsprintf($conn_r, '(commit.authorPHID IS NULL OR commit.authorPHID != %s)
       OR (req.auditorPHID = %s)', $this->awaitingUser->getPHID(), $this->awaitingUser->getPHID());
     }
     $status = $this->status;
     switch ($status) {
         case self::STATUS_OPEN:
             $where[] = qsprintf($conn_r, 'req.auditStatus in (%Ls)', PhabricatorAuditStatusConstants::getOpenStatusConstants());
             if ($this->awaitingUser) {
                 $where[] = qsprintf($conn_r, 'awaiting.auditStatus IS NULL OR awaiting.auditStatus != %s', PhabricatorAuditStatusConstants::RESIGNED);
             }
             break;
         case self::STATUS_ANY:
             break;
         default:
             throw new Exception("Unknown status '{$status}'!");
     }
     if ($where) {
         $where = 'WHERE (' . implode(') AND (', $where) . ')';
     } else {
         $where = '';
     }
     return $where;
 }