mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-01 11:12:42 +01:00
74de24909b
Summary: Fixes T3661. Ref T3718. This makes Releeph custom fields extend PhabricatorCustomField so we can start moving over other pieces of infrastructure (rendering, storage, etc) to run through the same pathways. It's roughly the minimum amount of work required to be able to move forward. NOTE: This removes per-project custom field selectors. Fields are now configured for an entire install. My understanding is that Facebook does not use this feature, and modern field infrastructure has moved away from selectors. Test Plan: Viewed and edited projects, branches, and requests in Releeph. Grepped for removed config. Grepped for `field_selector`. Reviewers: btrahan Reviewed By: btrahan CC: LegNeato, aran Maniphest Tasks: T3661, T3718 Differential Revision: https://secure.phabricator.com/D6750
292 lines
9.1 KiB
PHP
292 lines
9.1 KiB
PHP
<?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 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->renderReleephEditControl($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));
|
|
|
|
return $this->buildApplicationPage(
|
|
array(
|
|
$crumbs,
|
|
$notice_view,
|
|
$error_view,
|
|
$form,
|
|
),
|
|
array(
|
|
'title' => $title,
|
|
));
|
|
}
|
|
}
|