protected function execute(ConduitAPIRequest $request)
 {
     $query = new PhabricatorAuditQuery();
     $auditor_phids = $request->getValue('auditorPHIDs', array());
     if ($auditor_phids) {
         $query->withAuditorPHIDs($auditor_phids);
     }
     $commit_phids = $request->getValue('commitPHIDs', array());
     if ($commit_phids) {
         $query->withCommitPHIDs($commit_phids);
     }
     $status = $request->getValue('status', PhabricatorAuditQuery::STATUS_ANY);
     $query->withStatus($status);
     $query->setOffset($request->getValue('offset', 0));
     $query->setLimit($request->getValue('limit', 100));
     $requests = $query->execute();
     $results = array();
     foreach ($requests as $request) {
         $results[] = array('id' => $request->getID(), 'commitPHID' => $request->getCommitPHID(), 'auditorPHID' => $request->getAuditorPHID(), 'reasons' => $request->getAuditReasons(), 'status' => $request->getAuditStatus());
     }
     return $results;
 }
 public function buildAuditPanel()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
     $query = new PhabricatorAuditQuery();
     $query->withAuditorPHIDs($phids);
     $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
     $query->withAwaitingUser($user);
     $query->needCommitData(true);
     $query->setLimit(10);
     $audits = $query->execute();
     $commits = $query->getCommits();
     if (!$audits) {
         return $this->renderMinipanel('No Audits', 'No commits are waiting for you to audit them.');
     }
     $view = new PhabricatorAuditListView();
     $view->setAudits($audits);
     $view->setCommits($commits);
     $view->setUser($user);
     $phids = $view->getRequiredHandlePHIDs();
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $view->setHandles($handles);
     $panel = new AphrontPanelView();
     $panel->setHeader('Audits');
     $panel->setCaption('Commits awaiting your audit.');
     $panel->appendChild($view);
     $panel->addButton(phutil_render_tag('a', array('href' => '/audit/', 'class' => 'button grey'), "View Active Audits »"));
     return $panel;
 }
 public function processRequest()
 {
     $drequest = $this->getDiffusionRequest();
     $request = $this->getRequest();
     $user = $request->getUser();
     $callsign = $drequest->getRepository()->getCallsign();
     $content = array();
     $content[] = $this->buildCrumbs(array('commit' => true));
     $repository = $drequest->getRepository();
     $commit = $drequest->loadCommit();
     if (!$commit) {
         // TODO: Make more user-friendly.
         throw new Exception('This commit has not parsed yet.');
     }
     $commit_data = $drequest->loadCommitData();
     $commit->attachCommitData($commit_data);
     $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
     if ($is_foreign) {
         $subpath = $commit_data->getCommitDetail('svn-subpath');
         $error_panel = new AphrontErrorView();
         $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
         $error_panel->setTitle('Commit Not Tracked');
         $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
         $error_panel->appendChild("This Diffusion repository is configured to track only one " . "subdirectory of the entire Subversion repository, and this commit " . "didn't affect the tracked subdirectory ('" . phutil_escape_html($subpath) . "'), so no information is available.");
         $content[] = $error_panel;
     } else {
         $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
         require_celerity_resource('diffusion-commit-view-css');
         require_celerity_resource('phabricator-remarkup-css');
         $parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest);
         $headsup_panel = new AphrontHeadsupView();
         $headsup_panel->setHeader('Commit Detail');
         $headsup_panel->setActionList($this->renderHeadsupActionList($commit));
         $headsup_panel->setProperties($this->getCommitProperties($commit, $commit_data, $parent_query->loadParents()));
         $headsup_panel->appendChild('<div class="diffusion-commit-message phabricator-remarkup">' . $engine->markupText($commit_data->getCommitMessage()) . '</div>');
         $content[] = $headsup_panel;
     }
     $query = new PhabricatorAuditQuery();
     $query->withCommitPHIDs(array($commit->getPHID()));
     $audit_requests = $query->execute();
     $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
     $content[] = $this->buildAuditTable($commit, $audit_requests);
     $content[] = $this->buildComments($commit);
     $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest($drequest);
     $changes = $change_query->loadChanges();
     $content[] = $this->buildMergesTable($commit);
     $original_changes_count = count($changes);
     if ($request->getStr('show_all') !== 'true' && $original_changes_count > self::CHANGES_LIMIT) {
         $changes = array_slice($changes, 0, self::CHANGES_LIMIT);
     }
     $change_table = new DiffusionCommitChangeTableView();
     $change_table->setDiffusionRequest($drequest);
     $change_table->setPathChanges($changes);
     $count = count($changes);
     $bad_commit = null;
     if ($count == 0) {
         $bad_commit = queryfx_one(id(new PhabricatorRepository())->establishConnection('r'), 'SELECT * FROM %T WHERE fullCommitName = %s', PhabricatorRepository::TABLE_BADCOMMIT, 'r' . $callsign . $commit->getCommitIdentifier());
     }
     if ($bad_commit) {
         $error_panel = new AphrontErrorView();
         $error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
         $error_panel->setTitle('Bad Commit');
         $error_panel->appendChild(phutil_escape_html($bad_commit['description']));
         $content[] = $error_panel;
     } else {
         if ($is_foreign) {
             // Don't render anything else.
         } else {
             if (!count($changes)) {
                 $no_changes = new AphrontErrorView();
                 $no_changes->setWidth(AphrontErrorView::WIDTH_WIDE);
                 $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
                 $no_changes->setTitle('Not Yet Parsed');
                 // TODO: This can also happen with weird SVN changes that don't do
                 // anything (or only alter properties?), although the real no-changes case
                 // is extremely rare and might be impossible to produce organically. We
                 // should probably write some kind of "Nothing Happened!" change into the
                 // DB once we parse these changes so we can distinguish between
                 // "not parsed yet" and "no changes".
                 $no_changes->appendChild("This commit hasn't been fully parsed yet (or doesn't affect any " . "paths).");
                 $content[] = $no_changes;
             } else {
                 $change_panel = new AphrontPanelView();
                 $change_panel->setHeader("Changes (" . number_format($count) . ")");
                 if ($count !== $original_changes_count) {
                     $show_all_button = phutil_render_tag('a', array('class' => 'button green', 'href' => '?show_all=true'), phutil_escape_html('Show All Changes'));
                     $warning_view = id(new AphrontErrorView())->setSeverity(AphrontErrorView::SEVERITY_WARNING)->setTitle(sprintf("Showing only the first %d changes out of %s!", self::CHANGES_LIMIT, number_format($original_changes_count)));
                     $change_panel->appendChild($warning_view);
                     $change_panel->addButton($show_all_button);
                 }
                 $change_panel->appendChild($change_table);
                 $content[] = $change_panel;
                 $changesets = DiffusionPathChange::convertToDifferentialChangesets($changes);
                 $vcs = $repository->getVersionControlSystem();
                 switch ($vcs) {
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
                         $vcs_supports_directory_changes = true;
                         break;
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
                     case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
                         $vcs_supports_directory_changes = false;
                         break;
                     default:
                         throw new Exception("Unknown VCS.");
                 }
                 $references = array();
                 foreach ($changesets as $key => $changeset) {
                     $file_type = $changeset->getFileType();
                     if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
                         if (!$vcs_supports_directory_changes) {
                             unset($changesets[$key]);
                             continue;
                         }
                     }
                     $references[$key] = $drequest->generateURI(array('action' => 'rendering-ref', 'path' => $changeset->getFilename()));
                 }
                 // TODO: Some parts of the views still rely on properties of the
                 // DifferentialChangeset. Make the objects ephemeral to make sure we don't
                 // accidentally save them, and then set their ID to the appropriate ID for
                 // this application (the path IDs).
                 $pquery = new DiffusionPathIDQuery(mpull($changesets, 'getFilename'));
                 $path_ids = $pquery->loadPathIDs();
                 foreach ($changesets as $changeset) {
                     $changeset->makeEphemeral();
                     $changeset->setID($path_ids[$changeset->getFilename()]);
                 }
                 $change_list = new DifferentialChangesetListView();
                 $change_list->setChangesets($changesets);
                 $change_list->setRenderingReferences($references);
                 $change_list->setRenderURI('/diffusion/' . $callsign . '/diff/');
                 $change_list->setRepository($repository);
                 $change_list->setUser($user);
                 $change_list->setStandaloneURI('/diffusion/' . $callsign . '/diff/');
                 $change_list->setRawFileURIs(null, '/diffusion/' . $callsign . '/diff/?view=r');
                 $change_list->setInlineCommentControllerURI('/diffusion/inline/' . phutil_escape_uri($commit->getPHID()) . '/');
                 // TODO: This is pretty awkward, unify the CSS between Diffusion and
                 // Differential better.
                 require_celerity_resource('differential-core-view-css');
                 $change_list = '<div class="differential-primary-pane">' . $change_list->render() . '</div>';
                 $content[] = $change_list;
             }
         }
     }
     $content[] = $this->buildAddCommentView($commit, $audit_requests);
     return $this->buildStandardPageResponse($content, array('title' => 'r' . $callsign . $commit->getCommitIdentifier()));
 }
 private function buildAuditView(PhabricatorObjectHandle $handle = null)
 {
     $request = $this->getRequest();
     $query = new PhabricatorAuditQuery();
     $use_pager = $this->filter != 'active';
     if ($use_pager) {
         $pager = new AphrontPagerView();
         $pager->setURI($request->getRequestURI(), 'offset');
         $pager->setOffset($request->getInt('offset'));
         $query->setOffset($pager->getOffset());
         $query->setLimit($pager->getPageSize() + 1);
     }
     $awaiting = null;
     $phids = null;
     switch ($this->filter) {
         case 'user':
         case 'active':
             $obj = id(new PhabricatorUser())->loadOneWhere('phid = %s', $handle->getPHID());
             if (!$obj) {
                 throw new Exception("Invalid user!");
             }
             $phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($obj);
             $awaiting = $obj;
             break;
         case 'project':
         case 'package':
             $phids = array($handle->getPHID());
             break;
         case 'audits':
             break;
         default:
             throw new Exception("Unknown filter!");
     }
     if ($phids) {
         $query->withAuditorPHIDs($phids);
     }
     if ($awaiting) {
         $query->withAwaitingUser($awaiting);
     }
     switch ($this->filter) {
         case 'audits':
         case 'user':
         case 'project':
         case 'package':
             switch ($this->filterStatus) {
                 case 'open':
                     $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
                     break;
             }
             break;
         case 'active':
             $query->withStatus(PhabricatorAuditQuery::STATUS_OPEN);
             break;
     }
     if ($handle) {
         $handle_name = phutil_escape_html($handle->getName());
     } else {
         $handle_name = null;
     }
     switch ($this->filter) {
         case 'active':
             $header = 'Required Audits';
             $nodata = 'No commits require your audit.';
             break;
         case 'user':
             $header = "Audits for {$handle_name}";
             $nodata = "No matching audits by {$handle_name}.";
             break;
         case 'audits':
             $header = "Audits";
             $nodata = "No matching audits.";
             break;
         case 'project':
             $header = "Audits in Project '{$handle_name}'";
             $nodata = "No matching audits in project '{$handle_name}'.";
             break;
         case 'package':
             $header = "Audits for Package '{$handle_name}'";
             $nodata = "No matching audits in package '{$handle_name}'.";
             break;
     }
     $query->needCommitData(true);
     $audits = $query->execute();
     if ($use_pager) {
         $audits = $pager->sliceResults($audits);
     }
     $view = new PhabricatorAuditListView();
     $view->setAudits($audits);
     $view->setCommits($query->getCommits());
     $view->setNoDataString($nodata);
     $phids = $view->getRequiredHandlePHIDs();
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $view->setHandles($handles);
     $panel = new AphrontPanelView();
     $panel->setHeader($header);
     $panel->appendChild($view);
     if ($use_pager) {
         $panel->appendChild($pager);
     }
     return $panel;
 }