private function loadRevisions($phid)
 {
     $table = new DifferentialRevision();
     $conn_r = $table->establishConnection('r');
     $rows = queryfx_all($conn_r, 'SELECT revisions.* FROM %T revisions ' . 'JOIN %T comments ON comments.revisionID = revisions.id ' . 'JOIN (' . ' SELECT revisionID FROM %T WHERE objectPHID = %s ' . ' UNION ALL ' . ' SELECT id from differential_revision WHERE authorPHID = %s) rel ' . 'ON (comments.revisionID = rel.revisionID)' . 'WHERE comments.action = %s' . 'AND comments.authorPHID = %s', $table->getTableName(), id(new DifferentialComment())->getTableName(), DifferentialRevision::RELATIONSHIP_TABLE, $phid, $phid, $this->filter, $phid);
     return $table->loadAllFromArray($rows);
 }
 protected function readValueFromRevision(DifferentialRevision $revision)
 {
     if (!$revision->getPHID()) {
         return array();
     }
     return PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), DifferentialRevisionHasTaskEdgeType::EDGECONST);
 }
 protected function readValueFromRevision(DifferentialRevision $revision)
 {
     if (!$revision->getPHID()) {
         return array();
     }
     return PhabricatorSubscribersQuery::loadSubscribersForPHID($revision->getPHID());
 }
 public function __construct(DifferentialRevision $revision, $mode)
 {
     $this->revision = $revision;
     $this->mode = $mode;
     $comments = id(new DifferentialComment())->loadAllWhere('revisionID = %d', $revision->getID());
     $this->comments = $comments;
 }
 protected function readValueFromRevision(DifferentialRevision $revision)
 {
     if (!$revision->getPHID()) {
         return array();
     }
     $projects = PhabricatorEdgeQuery::loadDestinationPHIDs($revision->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
     $projects = array_reverse($projects);
     return $projects;
 }
 /**
  * Check if this action should be disabled, and explain why.
  *
  * By default, this method checks for push permissions, and for the
  * revision being Accepted.
  *
  * @return False for "not disabled"; human-readable text explaining why, if
  *         it is disabled.
  */
 public function isActionDisabled(PhabricatorUser $viewer, DifferentialRevision $revision, PhabricatorRepository $repository)
 {
     $status = $revision->getStatus();
     if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) {
         return pht('Only Accepted revisions can be landed.');
     }
     if (!PhabricatorPolicyFilter::hasCapability($viewer, $repository, DiffusionPushCapability::CAPABILITY)) {
         return pht('You do not have permissions to push to this repository.');
     }
     return false;
 }
 public function testReviewerStatsRequiresReview()
 {
     $revision = new DifferentialRevision();
     $revision->setDateCreated(1);
     $revision->attachRelationships(array($this->newReviewer('R')));
     $comments = array();
     $stats = new DifferentialReviewerStats();
     $stats->setUntil(2);
     list($reviewed, $not_reviewed) = $stats->computeTimes($revision, $comments);
     $this->assertEqual(array(), $reviewed);
     $this->assertEqual(array('R' => array(2 - 1)), $not_reviewed);
 }
 protected function readValueFromRevision(DifferentialRevision $revision)
 {
     $phids = array();
     foreach ($revision->getReviewerStatus() as $reviewer) {
         switch ($reviewer->getStatus()) {
             case DifferentialReviewerStatus::STATUS_ACCEPTED:
             case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER:
                 $phids[] = $reviewer->getReviewerPHID();
                 break;
         }
     }
     return $phids;
 }
 protected function hasReviewersWithStatus(DifferentialRevision $revision, array $phids, array $statuses)
 {
     foreach ($revision->getReviewerStatus() as $reviewer) {
         $reviewer_phid = $reviewer->getReviewerPHID();
         if (empty($phids[$reviewer_phid])) {
             continue;
         }
         $status = $reviewer->getStatus();
         if (empty($statuses[$status])) {
             continue;
         }
         return true;
     }
     return false;
 }
 public static function loadFromStorage(DifferentialRevision $revision, array $aux_fields)
 {
     $storage_keys = array_filter(mpull($aux_fields, 'getStorageKey'));
     $field_data = array();
     if ($storage_keys) {
         $field_data = id(new DifferentialAuxiliaryField())->loadAllWhere('revisionPHID = %s AND name IN (%Ls)', $revision->getPHID(), $storage_keys);
         $field_data = mpull($field_data, 'getValue', 'getName');
     }
     foreach ($aux_fields as $aux_field) {
         $aux_field->setRevision($revision);
         $key = $aux_field->getStorageKey();
         if ($key) {
             $aux_field->setValueFromStorage(idx($field_data, $key));
         }
     }
     return $aux_fields;
 }
 public function commitRevisionToWorkspace(DifferentialRevision $revision, ArcanistRepositoryAPI $workspace, PhabricatorUser $user)
 {
     $diff_id = $revision->loadActiveDiff()->getID();
     $call = new ConduitCall('differential.getrawdiff', array('diffID' => $diff_id));
     $call->setUser($user);
     $raw_diff = $call->execute();
     $future = $workspace->execFutureLocal('patch --no-commit -');
     $future->write($raw_diff);
     $future->resolvex();
     $workspace->reloadWorkingCopy();
     $call = new ConduitCall('differential.getcommitmessage', array('revision_id' => $revision->getID()));
     $call->setUser($user);
     $message = $call->execute();
     $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $revision->getAuthorPHID());
     $author_string = sprintf('%s <%s>', $author->getRealName(), $author->loadPrimaryEmailAddress());
     $author_date = $revision->getDateCreated();
     $workspace->execxLocal('commit --date=%s --user=%s ' . '--message=%s', $author_date . ' 0', $author_string, $message);
 }
 public static function loadUnsubmittedInlineComments(PhabricatorUser $viewer, DifferentialRevision $revision)
 {
     // TODO: This probably needs to move somewhere more central as we move
     // away from DifferentialInlineCommentQuery, but
     // PhabricatorApplicationTransactionCommentQuery is currently `final` and
     // I'm not yet decided on how to approach that. For now, just get the PHIDs
     // and then execute a PHID-based query through the standard stack.
     $table = new DifferentialTransactionComment();
     $conn_r = $table->establishConnection('r');
     $phids = queryfx_all($conn_r, 'SELECT phid FROM %T
     WHERE revisionPHID = %s
       AND authorPHID = %s
       AND transactionPHID IS NULL', $table->getTableName(), $revision->getPHID(), $viewer->getPHID());
     $phids = ipull($phids, 'phid');
     if (!$phids) {
         return array();
     }
     return id(new PhabricatorApplicationTransactionCommentQuery())->setTemplate(new DifferentialTransactionComment())->setViewer($viewer)->withPHIDs($phids)->execute();
 }
 protected function execute(ConduitAPIRequest $request)
 {
     $viewer = $request->getUser();
     $diff = id(new DifferentialDiffQuery())->setViewer($viewer)->withIDs(array($request->getValue('diffid')))->executeOne();
     if (!$diff) {
         throw new ConduitException('ERR_BAD_DIFF');
     }
     $revision = DifferentialRevision::initializeNewRevision($viewer);
     $revision->attachReviewerStatus(array());
     $this->applyFieldEdit($request, $revision, $diff, $request->getValue('fields', array()), $message = null);
     return array('revisionid' => $revision->getID(), 'uri' => PhabricatorEnv::getURI('/D' . $revision->getID()));
 }
 public function commitRevisionToWorkspace(DifferentialRevision $revision, ArcanistRepositoryAPI $workspace, PhabricatorUser $user)
 {
     $diff_id = $revision->loadActiveDiff()->getID();
     $call = new ConduitCall('differential.getrawdiff', array('diffID' => $diff_id));
     $call->setUser($user);
     $raw_diff = $call->execute();
     $missing_binary = "\nindex " . "0000000000000000000000000000000000000000.." . "0000000000000000000000000000000000000000\n";
     if (strpos($raw_diff, $missing_binary) !== false) {
         throw new Exception(pht('Patch is missing content for a binary file'));
     }
     $future = $workspace->execFutureLocal('apply --index -');
     $future->write($raw_diff);
     $future->resolvex();
     $workspace->reloadWorkingCopy();
     $call = new ConduitCall('differential.getcommitmessage', array('revision_id' => $revision->getID()));
     $call->setUser($user);
     $message = $call->execute();
     $author = id(new PhabricatorUser())->loadOneWhere('phid = %s', $revision->getAuthorPHID());
     $author_string = sprintf('%s <%s>', $author->getRealName(), $author->loadPrimaryEmailAddress());
     $author_date = $revision->getDateCreated();
     $workspace->execxLocal('-c user.name=%s -c user.email=%s ' . 'commit --date=%s --author=%s ' . '--message=%s', $user->getRealName(), $user->loadPrimaryEmailAddress(), $author_date, $author_string, $message);
 }
 public function generateObject()
 {
     $author = $this->loadPhabrictorUser();
     $revision = DifferentialRevision::initializeNewRevision($author);
     $revision->attachReviewerStatus(array());
     $revision->attachActiveDiff(null);
     // This could be a bit richer and more formal than it is.
     $revision->setTitle($this->generateTitle());
     $revision->setSummary($this->generateDescription());
     $revision->setTestPlan($this->generateDescription());
     $diff = $this->generateDiff($author);
     $xactions = array();
     $xactions[] = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_UPDATE)->setNewValue($diff->getPHID());
     id(new DifferentialTransactionEditor())->setActor($author)->setContentSource($this->getLipsumContentSource())->applyTransactions($revision, $xactions);
     return $revision;
 }
 private function attachToRevision(DifferentialRevision $revision, $actor_phid)
 {
     $drequest = DiffusionRequest::newFromDictionary(array('repository' => $this->repository, 'commit' => $this->commit->getCommitIdentifier()));
     $raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)->loadRawDiff();
     $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff);
     $diff = DifferentialDiff::newFromRawChanges($changes)->setRevisionID($revision->getID())->setAuthorPHID($actor_phid)->setCreationMethod('commit')->setSourceControlSystem($this->repository->getVersionControlSystem())->setLintStatus(DifferentialLintStatus::LINT_SKIP)->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP)->setDateCreated($this->commit->getEpoch())->setDescription('Commit r' . $this->repository->getCallsign() . $this->commit->getCommitIdentifier());
     // TODO: This is not correct in SVN where one repository can have multiple
     // Arcanist projects.
     $arcanist_project = id(new PhabricatorRepositoryArcanistProject())->loadOneWhere('repositoryID = %d LIMIT 1', $this->repository->getID());
     if ($arcanist_project) {
         $diff->setArcanistProjectPHID($arcanist_project->getPHID());
     }
     $parents = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest)->loadParents();
     if ($parents) {
         $diff->setSourceControlBaseRevision(head_key($parents));
     }
     // TODO: Attach binary files.
     $revision->setLineCount($diff->getLineCount());
     return $diff->save();
 }
 private function loadData()
 {
     $table = new DifferentialRevision();
     $conn_r = $table->establishConnection('r');
     if ($this->draftAuthors) {
         $draft_key = 'differential-comment-';
         $drafts = id(new PhabricatorDraft())->loadAllWhere('authorPHID IN (%Ls) AND draftKey LIKE %> AND draft != %s', $this->draftAuthors, $draft_key, '');
         $this->draftRevisions = array();
         $len = strlen($draft_key);
         foreach ($drafts as $draft) {
             $this->draftRevisions[] = substr($draft->getDraftKey(), $len);
         }
     }
     $select = qsprintf($conn_r, 'SELECT r.* FROM %T r', $table->getTableName());
     $joins = $this->buildJoinsClause($conn_r);
     $where = $this->buildWhereClause($conn_r);
     $group_by = $this->buildGroupByClause($conn_r);
     $order_by = $this->buildOrderByClause($conn_r);
     $limit = '';
     if ($this->offset || $this->limit) {
         $limit = qsprintf($conn_r, 'LIMIT %d, %d', (int) $this->offset, $this->limit);
     }
     return queryfx_all($conn_r, '%Q %Q %Q %Q %Q %Q', $select, $joins, $where, $group_by, $order_by, $limit);
 }
 /**
  * Update the table connecting revisions to DVCS local hashes, so we can
  * identify revisions by commit/tree hashes.
  */
 private function updateRevisionHashTable(DifferentialRevision $revision, DifferentialDiff $diff)
 {
     $vcs = $diff->getSourceControlSystem();
     if ($vcs == DifferentialRevisionControlSystem::SVN) {
         // Subversion has no local commit or tree hash information, so we don't
         // have to do anything.
         return;
     }
     $property = id(new DifferentialDiffProperty())->loadOneWhere('diffID = %d AND name = %s', $diff->getID(), 'local:commits');
     if (!$property) {
         return;
     }
     $hashes = array();
     $data = $property->getData();
     switch ($vcs) {
         case DifferentialRevisionControlSystem::GIT:
             foreach ($data as $commit) {
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_GIT_COMMIT, $commit['commit']);
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_GIT_TREE, $commit['tree']);
             }
             break;
         case DifferentialRevisionControlSystem::MERCURIAL:
             foreach ($data as $commit) {
                 $hashes[] = array(ArcanistDifferentialRevisionHash::HASH_MERCURIAL_COMMIT, $commit['rev']);
             }
             break;
     }
     $conn_w = $revision->establishConnection('w');
     $sql = array();
     foreach ($hashes as $info) {
         list($type, $hash) = $info;
         $sql[] = qsprintf($conn_w, '(%d, %s, %s)', $revision->getID(), $type, $hash);
     }
     queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', ArcanistDifferentialRevisionHash::TABLE_NAME, $revision->getID());
     if ($sql) {
         queryfx($conn_w, 'INSERT INTO %T (revisionID, type, hash) VALUES %Q', ArcanistDifferentialRevisionHash::TABLE_NAME, implode(', ', $sql));
     }
 }
 private function rejectOperation(DifferentialRevision $revision, $title, $body)
 {
     $id = $revision->getID();
     $detail_uri = "/D{$id}";
     return $this->newDialog()->setTitle($title)->appendParagraph($body)->addCancelButton($detail_uri);
 }
 private function buildSelectStatement(AphrontDatabaseConnection $conn_r)
 {
     $table = new DifferentialRevision();
     $select = qsprintf($conn_r, 'SELECT r.* FROM %T r', $table->getTableName());
     $joins = $this->buildJoinsClause($conn_r);
     $where = $this->buildWhereClause($conn_r);
     $group_by = $this->buildGroupByClause($conn_r);
     $this->buildingGlobalOrder = false;
     $order_by = $this->buildOrderClause($conn_r);
     $limit = $this->buildLimitClause($conn_r);
     return qsprintf($conn_r, '(%Q %Q %Q %Q %Q %Q)', $select, $joins, $where, $group_by, $order_by, $limit);
 }
<?php

echo pht('Migrating Differential unsubscribed users to edges...') . "\n";
$table = new DifferentialRevision();
$table->openTransaction();
// We couldn't use new LiskMigrationIterator($table) because the $unsubscribed
// property gets deleted.
$revs = queryfx_all($table->establishConnection('w'), 'SELECT id, phid, unsubscribed FROM differential_revision');
foreach ($revs as $rev) {
    echo '.';
    $unsubscribed = json_decode($rev['unsubscribed']);
    if (!$unsubscribed) {
        continue;
    }
    $editor = new PhabricatorEdgeEditor();
    foreach ($unsubscribed as $user_phid => $_) {
        $editor->addEdge($rev['phid'], PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST, $user_phid);
    }
    $editor->save();
}
$table->saveTransaction();
echo pht('Done.') . "\n";
 private function unsubscribeUser(DifferentialRevision $revision, PhabricatorUser $user)
 {
     $revision->loadRelationships();
     DifferentialRevisionEditor::removeCCAndUpdateRevision($revision, $user->getPHID(), $user->getPHID());
 }
 public static function renderTagForRevision(DifferentialRevision $revision)
 {
     $status = $revision->getStatus();
     $status_name = ArcanistDifferentialRevisionStatus::getNameForRevisionStatus($status);
     return id(new PHUITagView())->setType(PHUITagView::TYPE_STATE)->setName($status_name);
 }
 public static function indexRevision(DifferentialRevision $rev)
 {
     $doc = new PhabricatorSearchAbstractDocument();
     $doc->setPHID($rev->getPHID());
     $doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_DREV);
     $doc->setDocumentTitle($rev->getTitle());
     $doc->setDocumentCreated($rev->getDateCreated());
     $doc->setDocumentModified($rev->getDateModified());
     $doc->addField(PhabricatorSearchField::FIELD_BODY, $rev->getSummary());
     $doc->addField(PhabricatorSearchField::FIELD_TEST_PLAN, $rev->getTestPlan());
     $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     if ($rev->getStatus() != ArcanistDifferentialRevisionStatus::CLOSED && $rev->getStatus() != ArcanistDifferentialRevisionStatus::ABANDONED) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OPEN, $rev->getPHID(), PhabricatorPHIDConstants::PHID_TYPE_DREV, time());
     }
     $comments = id(new DifferentialComment())->loadAllWhere('revisionID = %d', $rev->getID());
     $inlines = id(new DifferentialInlineComment())->loadAllWhere('revisionID = %d AND commentID IS NOT NULL', $rev->getID());
     $touches = array();
     foreach (array_merge($comments, $inlines) as $comment) {
         if (strlen($comment->getContent())) {
             $doc->addField(PhabricatorSearchField::FIELD_COMMENT, $comment->getContent());
         }
         $author = $comment->getAuthorPHID();
         $touches[$author] = $comment->getDateCreated();
     }
     foreach ($touches as $touch => $time) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_TOUCH, $touch, PhabricatorPHIDConstants::PHID_TYPE_USER, $time);
     }
     $rev->loadRelationships();
     // If a revision needs review, the owners are the reviewers. Otherwise, the
     // owner is the author (e.g., accepted, rejected, closed).
     if ($rev->getStatus() == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) {
         foreach ($rev->getReviewers() as $phid) {
             $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $phid, PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateModified());
             // Bogus timestamp.
         }
     } else {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_OWNER, $rev->getAuthorPHID(), PhabricatorPHIDConstants::PHID_TYPE_USER, $rev->getDateCreated());
     }
     $ccphids = $rev->getCCPHIDs();
     $handles = id(new PhabricatorObjectHandleData($ccphids))->loadHandles();
     foreach ($handles as $phid => $handle) {
         $doc->addRelationship(PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER, $phid, $handle->getType(), $rev->getDateModified());
         // Bogus timestamp.
     }
     self::reindexAbstractDocument($doc);
 }
 protected function writeValueToRevision(DifferentialRevision $revision, $value)
 {
     $revision->setSummary($value);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     if (!$id) {
         $id = $request->getInt('revisionID');
     }
     if ($id) {
         $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($id))->needRelationships(true)->needReviewerStatus(true)->needActiveDiffs(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$revision) {
             return new Aphront404Response();
         }
     } else {
         $revision = DifferentialRevision::initializeNewRevision($viewer);
         $revision->attachReviewerStatus(array());
     }
     $diff_id = $request->getInt('diffID');
     if ($diff_id) {
         $diff = id(new DifferentialDiffQuery())->setViewer($viewer)->withIDs(array($diff_id))->executeOne();
         if (!$diff) {
             return new Aphront404Response();
         }
         if ($diff->getRevisionID()) {
             // TODO: Redirect?
             throw new Exception(pht('This diff is already attached to a revision!'));
         }
     } else {
         $diff = null;
     }
     if (!$diff) {
         if (!$revision->getID()) {
             throw new Exception(pht('You can not create a new revision without a diff!'));
         }
     } else {
         // TODO: It would be nice to show the diff being attached in the UI.
     }
     $field_list = PhabricatorCustomField::getObjectFields($revision, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer)->readFieldsFromStorage($revision);
     if ($request->getStr('viaDiffView') && $diff) {
         $repo_key = id(new DifferentialRepositoryField())->getFieldKey();
         $repository_field = idx($field_list->getFields(), $repo_key);
         if ($repository_field) {
             $repository_field->setValue($request->getStr($repo_key));
         }
         $view_policy_key = id(new DifferentialViewPolicyField())->getFieldKey();
         $view_policy_field = idx($field_list->getFields(), $view_policy_key);
         if ($view_policy_field) {
             $view_policy_field->setValue($diff->getViewPolicy());
         }
     }
     $validation_exception = null;
     if ($request->isFormPost() && !$request->getStr('viaDiffView')) {
         $editor = id(new DifferentialTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true);
         $xactions = $field_list->buildFieldTransactionsFromRequest(new DifferentialTransaction(), $request);
         if ($diff) {
             $repository_phid = null;
             $repository_tokenizer = $request->getArr(id(new DifferentialRepositoryField())->getFieldKey());
             if ($repository_tokenizer) {
                 $repository_phid = reset($repository_tokenizer);
             }
             $xactions[] = id(new DifferentialTransaction())->setTransactionType(DifferentialTransaction::TYPE_UPDATE)->setNewValue($diff->getPHID());
             $editor->setRepositoryPHIDOverride($repository_phid);
         }
         $comments = $request->getStr('comments');
         if (strlen($comments)) {
             $xactions[] = id(new DifferentialTransaction())->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)->attachComment(id(new DifferentialTransactionComment())->setContent($comments));
         }
         try {
             $editor->applyTransactions($revision, $xactions);
             $revision_uri = '/D' . $revision->getID();
             return id(new AphrontRedirectResponse())->setURI($revision_uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
         }
     }
     $form = new AphrontFormView();
     $form->setUser($request->getUser());
     if ($diff) {
         $form->addHiddenInput('diffID', $diff->getID());
     }
     if ($revision->getID()) {
         $form->setAction('/differential/revision/edit/' . $revision->getID() . '/');
     } else {
         $form->setAction('/differential/revision/edit/');
     }
     if ($diff && $revision->getID()) {
         $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel(pht('Comments'))->setName('comments')->setCaption(pht("Explain what's new in this diff."))->setValue($request->getStr('comments')))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save')))->appendChild(id(new AphrontFormDividerControl()));
     }
     $field_list->appendFieldsToForm($form);
     $submit = id(new AphrontFormSubmitControl())->setValue('Save');
     if ($diff) {
         $submit->addCancelButton('/differential/diff/' . $diff->getID() . '/');
     } else {
         $submit->addCancelButton('/D' . $revision->getID());
     }
     $form->appendChild($submit);
     $crumbs = $this->buildApplicationCrumbs();
     if ($revision->getID()) {
         if ($diff) {
             $header_icon = 'fa-upload';
             $title = pht('Update Revision');
             $crumbs->addTextCrumb('D' . $revision->getID(), '/differential/diff/' . $diff->getID() . '/');
         } else {
             $header_icon = 'fa-pencil';
             $title = pht('Edit Revision: %s', $revision->getTitle());
             $crumbs->addTextCrumb('D' . $revision->getID(), '/D' . $revision->getID());
         }
     } else {
         $header_icon = 'fa-plus-square';
         $title = pht('Create New Differential Revision');
     }
     $form_box = id(new PHUIObjectBoxView())->setHeaderText('Revision')->setValidationException($validation_exception)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $crumbs->addTextCrumb($title);
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader($title)->setHeaderIcon($header_icon);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($form_box);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 /**
  * Note this code is somewhat similar to the buildPatch method in
  * @{class:DifferentialReviewRequestMail}.
  *
  * @return @{class:AphrontRedirectResponse}
  */
 private function buildRawDiffResponse(DifferentialRevision $revision, array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null)
 {
     assert_instances_of($changesets, 'DifferentialChangeset');
     assert_instances_of($vs_changesets, 'DifferentialChangeset');
     $viewer = $this->getRequest()->getUser();
     id(new DifferentialHunkQuery())->setViewer($viewer)->withChangesets($changesets)->needAttachToChangesets(true)->execute();
     $diff = new DifferentialDiff();
     $diff->attachChangesets($changesets);
     $raw_changes = $diff->buildChangesList();
     $changes = array();
     foreach ($raw_changes as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $loader = id(new PhabricatorFileBundleLoader())->setViewer($viewer);
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setLoadFileDataCallback(array($loader, 'loadFileData'));
     $vcs = $repository ? $repository->getVersionControlSystem() : null;
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
         case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
             $raw_diff = $bundle->toGitPatch();
             break;
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
         default:
             $raw_diff = $bundle->toUnifiedDiff();
             break;
     }
     $request_uri = $this->getRequest()->getRequestURI();
     // this ends up being something like
     //   D123.diff
     // or the verbose
     //   D123.vs123.id123.whitespaceignore-all.diff
     // lame but nice to include these options
     $file_name = ltrim($request_uri->getPath(), '/') . '.';
     foreach ($request_uri->getQueryParams() as $key => $value) {
         if ($key == 'download') {
             continue;
         }
         $file_name .= $key . $value . '.';
     }
     $file_name .= 'diff';
     $file = PhabricatorFile::buildFromFileDataOrHash($raw_diff, array('name' => $file_name, 'ttl' => 60 * 60 * 24, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE));
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
     $file->attachToObject($revision->getPHID());
     unset($unguarded);
     return $file->getRedirectResponse();
 }
 protected function writeValueToRevision(DifferentialRevision $revision, $value)
 {
     $revision->setRepositoryPHID($value);
 }
 protected function writeValueToRevision(DifferentialRevision $revision, $value)
 {
     $revision->setTestPlan($value);
 }
 public function loadHandles()
 {
     $types = phid_group_by_type($this->phids);
     $handles = array();
     $external_loaders = PhabricatorEnv::getEnvConfig('phid.external-loaders');
     foreach ($types as $type => $phids) {
         switch ($type) {
             case PhabricatorPHIDConstants::PHID_TYPE_MAGIC:
                 // Black magic!
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     switch ($phid) {
                         case ManiphestTaskOwner::OWNER_UP_FOR_GRABS:
                             $handle->setName('Up For Grabs');
                             $handle->setFullName('upforgrabs (Up For Grabs)');
                             $handle->setComplete(true);
                             break;
                         case ManiphestTaskOwner::PROJECT_NO_PROJECT:
                             $handle->setName('No Project');
                             $handle->setFullName('noproject (No Project)');
                             $handle->setComplete(true);
                             break;
                         default:
                             $handle->setName('Foul Magicks');
                             break;
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_USER:
                 $object = new PhabricatorUser();
                 $users = $object->loadAllWhere('phid IN (%Ls)', $phids);
                 $users = mpull($users, null, 'getPHID');
                 $image_phids = mpull($users, 'getProfileImagePHID');
                 $image_phids = array_unique(array_filter($image_phids));
                 $images = array();
                 if ($image_phids) {
                     $images = id(new PhabricatorFile())->loadAllWhere('phid IN (%Ls)', $image_phids);
                     $images = mpull($images, 'getBestURI', 'getPHID');
                 }
                 $statuses = id(new PhabricatorUserStatus())->loadCurrentStatuses($phids);
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($users[$phid])) {
                         $handle->setName('Unknown User');
                     } else {
                         $user = $users[$phid];
                         $handle->setName($user->getUsername());
                         $handle->setURI('/p/' . $user->getUsername() . '/');
                         $handle->setFullName($user->getUsername() . ' (' . $user->getRealName() . ')');
                         $handle->setAlternateID($user->getID());
                         $handle->setComplete(true);
                         if (isset($statuses[$phid])) {
                             $handle->setStatus($statuses[$phid]->getTextStatus());
                         }
                         $handle->setDisabled($user->getIsDisabled());
                         $img_uri = idx($images, $user->getProfileImagePHID());
                         if ($img_uri) {
                             $handle->setImageURI($img_uri);
                         } else {
                             $handle->setImageURI(PhabricatorUser::getDefaultProfileImageURI());
                         }
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_MLST:
                 $object = new PhabricatorMetaMTAMailingList();
                 $lists = $object->loadAllWhere('phid IN (%Ls)', $phids);
                 $lists = mpull($lists, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($lists[$phid])) {
                         $handle->setName('Unknown Mailing List');
                     } else {
                         $list = $lists[$phid];
                         $handle->setName($list->getName());
                         $handle->setURI($list->getURI());
                         $handle->setFullName($list->getName());
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_DREV:
                 $object = new DifferentialRevision();
                 $revs = $object->loadAllWhere('phid in (%Ls)', $phids);
                 $revs = mpull($revs, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($revs[$phid])) {
                         $handle->setName('Unknown Revision');
                     } else {
                         $rev = $revs[$phid];
                         $handle->setName($rev->getTitle());
                         $handle->setURI('/D' . $rev->getID());
                         $handle->setFullName('D' . $rev->getID() . ': ' . $rev->getTitle());
                         $handle->setComplete(true);
                         $status = $rev->getStatus();
                         if ($status == ArcanistDifferentialRevisionStatus::CLOSED || $status == ArcanistDifferentialRevisionStatus::ABANDONED) {
                             $closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
                             $handle->setStatus($closed);
                         }
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
                 $object = new PhabricatorRepositoryCommit();
                 $commits = $object->loadAllWhere('phid in (%Ls)', $phids);
                 $commits = mpull($commits, null, 'getPHID');
                 $repository_ids = array();
                 $callsigns = array();
                 if ($commits) {
                     $repository_ids = mpull($commits, 'getRepositoryID');
                     $repositories = id(new PhabricatorRepository())->loadAllWhere('id in (%Ld)', array_unique($repository_ids));
                     $callsigns = mpull($repositories, 'getCallsign');
                 }
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($commits[$phid]) || !isset($callsigns[$repository_ids[$phid]])) {
                         $handle->setName('Unknown Commit');
                     } else {
                         $commit = $commits[$phid];
                         $callsign = $callsigns[$repository_ids[$phid]];
                         $repository = $repositories[$repository_ids[$phid]];
                         $commit_identifier = $commit->getCommitIdentifier();
                         // In case where the repository for the commit was deleted,
                         // we don't have have info about the repository anymore.
                         if ($repository) {
                             $name = $repository->formatCommitName($commit_identifier);
                             $handle->setName($name);
                         } else {
                             $handle->setName('Commit ' . 'r' . $callsign . $commit_identifier);
                         }
                         $handle->setURI('/r' . $callsign . $commit_identifier);
                         $handle->setFullName('r' . $callsign . $commit_identifier);
                         $handle->setTimestamp($commit->getEpoch());
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_TASK:
                 $object = new ManiphestTask();
                 $tasks = $object->loadAllWhere('phid in (%Ls)', $phids);
                 $tasks = mpull($tasks, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($tasks[$phid])) {
                         $handle->setName('Unknown Revision');
                     } else {
                         $task = $tasks[$phid];
                         $handle->setName($task->getTitle());
                         $handle->setURI('/T' . $task->getID());
                         $handle->setFullName('T' . $task->getID() . ': ' . $task->getTitle());
                         $handle->setComplete(true);
                         $handle->setAlternateID($task->getID());
                         if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) {
                             $closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
                             $handle->setStatus($closed);
                         }
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_FILE:
                 $object = new PhabricatorFile();
                 $files = $object->loadAllWhere('phid IN (%Ls)', $phids);
                 $files = mpull($files, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($files[$phid])) {
                         $handle->setName('Unknown File');
                     } else {
                         $file = $files[$phid];
                         $handle->setName($file->getName());
                         $handle->setURI($file->getBestURI());
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_PROJ:
                 $object = new PhabricatorProject();
                 $projects = $object->loadAllWhere('phid IN (%Ls)', $phids);
                 $projects = mpull($projects, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($projects[$phid])) {
                         $handle->setName('Unknown Project');
                     } else {
                         $project = $projects[$phid];
                         $handle->setName($project->getName());
                         $handle->setURI('/project/view/' . $project->getID() . '/');
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_REPO:
                 $object = new PhabricatorRepository();
                 $repositories = $object->loadAllWhere('phid in (%Ls)', $phids);
                 $repositories = mpull($repositories, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($repositories[$phid])) {
                         $handle->setName('Unknown Repository');
                     } else {
                         $repository = $repositories[$phid];
                         $handle->setName($repository->getCallsign());
                         $handle->setURI('/diffusion/' . $repository->getCallsign() . '/');
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_OPKG:
                 $object = new PhabricatorOwnersPackage();
                 $packages = $object->loadAllWhere('phid in (%Ls)', $phids);
                 $packages = mpull($packages, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($packages[$phid])) {
                         $handle->setName('Unknown Package');
                     } else {
                         $package = $packages[$phid];
                         $handle->setName($package->getName());
                         $handle->setURI('/owners/package/' . $package->getID() . '/');
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_APRJ:
                 $project_dao = new PhabricatorRepositoryArcanistProject();
                 $projects = $project_dao->loadAllWhere('phid IN (%Ls)', $phids);
                 $projects = mpull($projects, null, 'getPHID');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($projects[$phid])) {
                         $handle->setName('Unknown Arcanist Project');
                     } else {
                         $project = $projects[$phid];
                         $handle->setName($project->getName());
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             case PhabricatorPHIDConstants::PHID_TYPE_WIKI:
                 $document_dao = new PhrictionDocument();
                 $content_dao = new PhrictionContent();
                 $conn = $document_dao->establishConnection('r');
                 $documents = queryfx_all($conn, 'SELECT * FROM %T document JOIN %T content
           ON document.contentID = content.id
           WHERE document.phid IN (%Ls)', $document_dao->getTableName(), $content_dao->getTableName(), $phids);
                 $documents = ipull($documents, null, 'phid');
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setPHID($phid);
                     $handle->setType($type);
                     if (empty($documents[$phid])) {
                         $handle->setName('Unknown Document');
                     } else {
                         $info = $documents[$phid];
                         $handle->setName($info['title']);
                         $handle->setURI(PhrictionDocument::getSlugURI($info['slug']));
                         $handle->setComplete(true);
                     }
                     $handles[$phid] = $handle;
                 }
                 break;
             default:
                 $loader = null;
                 if (isset($external_loaders[$type])) {
                     $loader = $external_loaders[$type];
                 } else {
                     if (isset($external_loaders['*'])) {
                         $loader = $external_loaders['*'];
                     }
                 }
                 if ($loader) {
                     $object = newv($loader, array());
                     $handles += $object->loadHandles($phids);
                     break;
                 }
                 foreach ($phids as $phid) {
                     $handle = new PhabricatorObjectHandle();
                     $handle->setType($type);
                     $handle->setPHID($phid);
                     $handle->setName('Unknown Object');
                     $handle->setFullName('An Unknown Object');
                     $handles[$phid] = $handle;
                 }
                 break;
         }
     }
     return $handles;
 }