Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/releeph/controller/request/ReleephRequestEditController.php b/src/applications/releeph/controller/request/ReleephRequestEditController.php
index 4843e6204d..61cb540795 100644
--- a/src/applications/releeph/controller/request/ReleephRequestEditController.php
+++ b/src/applications/releeph/controller/request/ReleephRequestEditController.php
@@ -1,269 +1,292 @@
<?php
final class ReleephRequestEditController extends ReleephProjectController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'requestID');
parent::willProcessRequest($data);
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$releeph_project = $this->getReleephProject();
$releeph_branch = $this->getReleephBranch();
$request_identifier = $request->getStr('requestIdentifierRaw');
$e_request_identifier = true;
// Load the RQ we're editing, or create a new one
if ($this->id) {
- $rq = id(new ReleephRequest())->load($this->id);
+ $rq = id(new ReleephRequestQuery())
+ ->setViewer($user)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
$is_edit = true;
} else {
$is_edit = false;
$rq = id(new ReleephRequest())
->setRequestUserPHID($user->getPHID())
->setBranchID($releeph_branch->getID())
->setInBranch(0);
}
// Load all the ReleephFieldSpecifications
$selector = $this->getReleephProject()->getReleephFieldSelector();
$fields = $selector->getFieldSpecifications();
foreach ($fields as $field) {
$field
->setReleephProject($releeph_project)
->setReleephBranch($releeph_branch)
->setReleephRequest($rq);
}
// <aidehua> epriestley: Is it common to pass around a referer URL to
// return from whence one came? [...]
// <epriestley> If you only have two places, maybe consider some parameter
// rather than the full URL.
switch ($request->getStr('origin')) {
case 'request':
$origin_uri = '/RQ'.$rq->getID();
break;
case 'branch':
default:
$origin_uri = $releeph_branch->getURI();
break;
}
// Make edits
$errors = array();
if ($request->isFormPost()) {
$xactions = array();
// The commit-identifier being requested...
if (!$is_edit) {
if ($request_identifier ===
ReleephRequestTypeaheadControl::PLACEHOLDER) {
$errors[] = "No commit ID was provided.";
$e_request_identifier = 'Required';
} else {
$pr_commit = null;
$finder = id(new ReleephCommitFinder())
->setUser($user)
->setReleephProject($releeph_project);
try {
$pr_commit = $finder->fromPartial($request_identifier);
} catch (Exception $e) {
$e_request_identifier = 'Invalid';
$errors[] =
"Request {$request_identifier} is probably not a valid commit";
$errors[] = $e->getMessage();
}
$pr_commit_data = null;
if (!$errors) {
$pr_commit_data = $pr_commit->loadCommitData();
if (!$pr_commit_data) {
$e_request_identifier = 'Not parsed yet';
$errors[] = "The requested commit hasn't been parsed yet.";
}
}
}
if (!$errors) {
$existing = id(new ReleephRequest())
->loadOneWhere('requestCommitPHID = %s AND branchID = %d',
$pr_commit->getPHID(), $releeph_branch->getID());
if ($existing) {
return id(new AphrontRedirectResponse())
->setURI('/releeph/request/edit/'.$existing->getID().
'?existing=1');
}
$xactions[] = id(new ReleephRequestTransaction())
->setTransactionType(ReleephRequestTransaction::TYPE_REQUEST)
->setNewValue($pr_commit->getPHID());
$xactions[] = id(new ReleephRequestTransaction())
->setTransactionType(ReleephRequestTransaction::TYPE_USER_INTENT)
// To help hide these implicit intents...
->setMetadataValue('isRQCreate', true)
->setMetadataValue('userPHID', $user->getPHID())
->setMetadataValue(
'isAuthoritative',
$releeph_project->isAuthoritative($user))
->setNewValue(ReleephRequest::INTENT_WANT);
}
}
if (!$errors) {
foreach ($fields as $field) {
if ($field->isEditable()) {
try {
$data = $request->getRequestData();
$value = idx($data, $field->getRequiredStorageKey());
$field->validate($value);
$xactions[] = id(new ReleephRequestTransaction())
->setTransactionType(ReleephRequestTransaction::TYPE_EDIT_FIELD)
->setMetadataValue('fieldClass', get_class($field))
->setNewValue($value);
} catch (ReleephFieldParseException $ex) {
$errors[] = $ex->getMessage();
}
}
}
}
if (!$errors) {
$editor = id(new ReleephRequestTransactionalEditor())
->setActor($user)
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request);
$editor->applyTransactions($rq, $xactions);
return id(new AphrontRedirectResponse())->setURI($origin_uri);
}
}
$releeph_branch->populateReleephRequestHandles($user, array($rq));
$handles = $rq->getHandles();
$age_string = '';
if ($is_edit) {
$age_string = phabricator_format_relative_time(
time() - $rq->getDateCreated()) . ' ago';
}
// Warn the user if we've been redirected here because we tried to
// re-request something.
$notice_view = null;
if ($request->getInt('existing')) {
$notice_messages = array(
'You are editing an existing pick request!',
hsprintf(
"Requested %s by %s",
$age_string,
$handles[$rq->getRequestUserPHID()]->renderLink())
);
$notice_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setErrors($notice_messages);
}
/**
* Build the rest of the page
*/
$error_view = null;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setErrors($errors);
$error_view->setTitle('Form Errors');
}
$form = id(new AphrontFormView())
->setUser($user);
if ($is_edit) {
$form
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Original Commit')
->setValue(
$handles[$rq->getRequestCommitPHID()]->renderLink()))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Requestor')
->setValue(hsprintf(
'%s %s',
$handles[$rq->getRequestUserPHID()]->renderLink(),
$age_string)));
} else {
$origin = null;
$diff_rev_id = $request->getStr('D');
if ($diff_rev_id) {
$diff_rev = id(new DifferentialRevision())->load($diff_rev_id);
$origin = '/D'.$diff_rev->getID();
$title = sprintf(
'D%d: %s',
$diff_rev_id,
$diff_rev->getTitle());
$form
->addHiddenInput('requestIdentifierRaw', 'D'.$diff_rev_id)
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Diff')
->setValue($title));
} else {
$origin = $releeph_branch->getURI();
$repo = $releeph_project->loadPhabricatorRepository();
$branch_cut_point = id(new PhabricatorRepositoryCommit())
->loadOneWhere(
'phid = %s',
$releeph_branch->getCutPointCommitPHID());
$form->appendChild(
id(new ReleephRequestTypeaheadControl())
->setName('requestIdentifierRaw')
->setLabel('Commit ID')
->setRepo($repo)
->setValue($request_identifier)
->setError($e_request_identifier)
->setStartTime($branch_cut_point->getEpoch())
->setCaption(
'Start typing to autocomplete on commit title, '.
'or give a Phabricator commit identifier like rFOO1234'));
}
}
// Fields
foreach ($fields as $field) {
if ($field->isEditable()) {
$control = $field->renderEditControl($request);
$form->appendChild($control);
}
}
+ $crumbs = $this->buildApplicationCrumbs();
+
if ($is_edit) {
$title = pht('Edit Releeph Request');
$submit_name = pht('Save');
+
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName('RQ'.$rq->getID())
+ ->setHref('/RQ'.$rq->getID()));
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Edit')));
+
} else {
$title = pht('Create Releeph Request');
$submit_name = pht('Create');
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('New Request')));
}
- $form
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->addCancelButton($origin_uri, 'Cancel')
- ->setValue($submit_name));
-
- $panel = id(new AphrontPanelView())
- ->setHeader($title)
- ->setWidth(AphrontPanelView::WIDTH_FORM)
- ->appendChild($form);
+ $form->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton($origin_uri, 'Cancel')
+ ->setValue($submit_name));
- return $this->buildStandardPageResponse(
- array($notice_view, $error_view, $panel),
- array('title', $title));
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $notice_view,
+ $error_view,
+ $form,
+ ),
+ array(
+ 'title' => $title,
+ ));
}
}
diff --git a/src/applications/releeph/storage/ReleephRequest.php b/src/applications/releeph/storage/ReleephRequest.php
index e8147b87c2..06b7b76564 100644
--- a/src/applications/releeph/storage/ReleephRequest.php
+++ b/src/applications/releeph/storage/ReleephRequest.php
@@ -1,311 +1,312 @@
<?php
final class ReleephRequest extends ReleephDAO
implements PhabricatorPolicyInterface {
protected $phid;
protected $branchID;
protected $requestUserPHID;
protected $details = array();
protected $userIntents = array();
protected $inBranch;
protected $pickStatus;
protected $mailKey;
// Information about the thing being requested
protected $requestCommitPHID;
// Information about the last commit to the releeph branch
protected $commitIdentifier;
protected $commitPHID;
// Pre-populated handles that we'll bulk load in ReleephBranch
private $handles;
/* -( Constants and helper methods )--------------------------------------- */
const INTENT_WANT = 'want';
const INTENT_PASS = 'pass';
const PICK_PENDING = 1; // old
const PICK_FAILED = 2;
const PICK_OK = 3;
const PICK_MANUAL = 4; // old
const REVERT_OK = 5;
const REVERT_FAILED = 6;
public function shouldBeInBranch() {
return
$this->getPusherIntent() == self::INTENT_WANT &&
/**
* We use "!= pass" instead of "== want" in case the requestor intent is
* not present. In other words, only revert if the requestor explicitly
* passed.
*/
$this->getRequestorIntent() != self::INTENT_PASS;
}
/**
* Will return INTENT_WANT if any pusher wants this request, and no pusher
* passes on this request.
*/
public function getPusherIntent() {
$project = $this->loadReleephProject();
if (!$project->getPushers()) {
return self::INTENT_WANT;
}
$found_pusher_want = false;
foreach ($this->userIntents as $phid => $intent) {
if ($project->isAuthoritativePHID($phid)) {
if ($intent == self::INTENT_PASS) {
return self::INTENT_PASS;
}
$found_pusher_want = true;
}
}
if ($found_pusher_want) {
return self::INTENT_WANT;
} else {
return null;
}
}
public function getRequestorIntent() {
return idx($this->userIntents, $this->requestUserPHID);
}
public function getStatus() {
return $this->calculateStatus();
}
private function calculateStatus() {
if ($this->shouldBeInBranch()) {
if ($this->getInBranch()) {
return ReleephRequestStatus::STATUS_PICKED;
} else {
return ReleephRequestStatus::STATUS_NEEDS_PICK;
}
} else {
if ($this->getInBranch()) {
return ReleephRequestStatus::STATUS_NEEDS_REVERT;
} else {
$has_been_in_branch = $this->getCommitIdentifier();
// Regardless of why we reverted something, always say reverted if it
// was once in the branch.
if ($has_been_in_branch) {
return ReleephRequestStatus::STATUS_REVERTED;
} elseif ($this->getPusherIntent() === ReleephRequest::INTENT_PASS) {
// Otherwise, if it has never been in the branch, explicitly say why:
return ReleephRequestStatus::STATUS_REJECTED;
} elseif ($this->getRequestorIntent() === ReleephRequest::INTENT_WANT) {
return ReleephRequestStatus::STATUS_REQUESTED;
} else {
return ReleephRequestStatus::STATUS_ABANDONED;
}
}
}
}
/* -( Lisk mechanics )----------------------------------------------------- */
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
'userIntents' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
- ReleephPHIDConstants::PHID_TYPE_RERQ);
+ ReleephPHIDTypeRequest::TYPECONST);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
/* -( Helpful accessors )--------------------------------------------------- */
public function setHandles($handles) {
$this->handles = $handles;
return $this;
}
public function getHandles() {
if (!$this->handles) {
throw new Exception(
"You must call ReleephBranch::populateReleephRequestHandles() first");
}
return $this->handles;
}
public function getDetail($key, $default = null) {
return idx($this->getDetails(), $key, $default);
}
public function setDetail($key, $value) {
$this->details[$key] = $value;
return $this;
}
public function getReason() {
// Backward compatibility: reason used to be called comments
$reason = $this->getDetail('reason');
if (!$reason) {
return $this->getDetail('comments');
}
return $reason;
}
public function getSummary() {
/**
* Instead, you can use:
* - getDetail('summary') // the actual user-chosen summary
* - getSummaryForDisplay() // falls back to the original commit title
*
* Or for the fastidious:
* - id(new ReleephSummaryFieldSpecification())
* ->setReleephRequest($rr)
* ->getValue() // programmatic equivalent to getDetail()
*/
throw new Exception(
"getSummary() has been deprecated!");
}
/**
* Allow a null summary, and fall back to the title of the commit.
*/
public function getSummaryForDisplay() {
$summary = $this->getDetail('summary');
if (!$summary) {
$pr_commit_data = $this->loadPhabricatorRepositoryCommitData();
if ($pr_commit_data) {
$message_lines = explode("\n", $pr_commit_data->getCommitMessage());
$message_lines = array_filter($message_lines);
$summary = head($message_lines);
}
}
if (!$summary) {
$summary = '(no summary given and commit message empty or unparsed)';
}
return $summary;
}
public function loadRequestCommitDiffPHID() {
$commit = $this->loadPhabricatorRepositoryCommit();
if ($commit) {
$edges = $this
->loadPhabricatorRepositoryCommit()
->loadRelativeEdges(PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV);
return head(array_keys($edges));
}
}
/* -( Loading external objects )------------------------------------------- */
public function loadReleephBranch() {
return $this->loadOneRelative(
new ReleephBranch(),
'id',
'getBranchID');
}
public function loadReleephProject() {
return $this->loadReleephBranch()->loadReleephProject();
}
public function loadEvents() {
return $this->loadRelatives(
new ReleephRequestEvent(),
'releephRequestID',
'getID',
'(1 = 1) ORDER BY dateCreated, id');
}
public function loadPhabricatorRepositoryCommit() {
return $this->loadOneRelative(
new PhabricatorRepositoryCommit(),
'phid',
'getRequestCommitPHID');
}
public function loadPhabricatorRepositoryCommitData() {
$commit = $this->loadPhabricatorRepositoryCommit();
if ($commit) {
return $commit->loadOneRelative(
new PhabricatorRepositoryCommitData(),
'commitID');
}
}
public function loadDifferentialRevision() {
$diff_phid = $this->loadRequestCommitDiffPHID();
if (!$diff_phid) {
return null;
}
return $this->loadOneRelative(
new DifferentialRevision(),
'phid',
'loadRequestCommitDiffPHID');
}
/* -( State change helpers )----------------------------------------------- */
public function setUserIntent(PhabricatorUser $user, $intent) {
$this->userIntents[$user->getPHID()] = $intent;
return $this;
}
/* -( Migrating to status-less ReleephRequests )--------------------------- */
protected function didReadData() {
if ($this->userIntents === null) {
$this->userIntents = array();
}
}
public function setStatus($value) {
throw new Exception('`status` is now deprecated!');
}
/* -( Make magic Lisk methods private )------------------------------------ */
private function setUserIntents(array $ar) {
return parent::setUserIntents($ar);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::POLICY_USER;
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 19:41 (6 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128078
Default Alt Text
(19 KB)

Event Timeline