mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Don't create invalid build steps while adding them
Summary: Ref T1049. Currently, the "add" dialog lets you select a build step type, but then immediately creates one. If you "cancel" from the edit screen, you end up with an empty (and almost certainly invalid) build step. Instead, don't create the step until it's valid. Test Plan: Add Step -> Pick Type -> Add Step -> Cancel no longer creates empty step. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T1049 Differential Revision: https://secure.phabricator.com/D8605
This commit is contained in:
parent
d6b937ca27
commit
6e3c17e6f9
4 changed files with 97 additions and 54 deletions
|
@ -50,6 +50,8 @@ final class PhabricatorApplicationHarbormaster extends PhabricatorApplication {
|
||||||
=> 'HarbormasterBuildableListController',
|
=> 'HarbormasterBuildableListController',
|
||||||
'step/' => array(
|
'step/' => array(
|
||||||
'add/(?:(?P<id>\d+)/)?' => 'HarbormasterStepAddController',
|
'add/(?:(?P<id>\d+)/)?' => 'HarbormasterStepAddController',
|
||||||
|
'new/(?P<plan>\d+)/(?P<class>[^/]+)/'
|
||||||
|
=> 'HarbormasterStepEditController',
|
||||||
'edit/(?:(?P<id>\d+)/)?' => 'HarbormasterStepEditController',
|
'edit/(?:(?P<id>\d+)/)?' => 'HarbormasterStepEditController',
|
||||||
'delete/(?:(?P<id>\d+)/)?' => 'HarbormasterStepDeleteController',
|
'delete/(?:(?P<id>\d+)/)?' => 'HarbormasterStepDeleteController',
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,47 +16,32 @@ final class HarbormasterStepAddController
|
||||||
$this->requireApplicationCapability(
|
$this->requireApplicationCapability(
|
||||||
HarbormasterCapabilityManagePlans::CAPABILITY);
|
HarbormasterCapabilityManagePlans::CAPABILITY);
|
||||||
|
|
||||||
$id = $this->id;
|
|
||||||
|
|
||||||
$plan = id(new HarbormasterBuildPlanQuery())
|
$plan = id(new HarbormasterBuildPlanQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($this->id))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$plan) {
|
if (!$plan) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$cancel_uri = $this->getApplicationURI('plan/'.$plan->getID().'/');
|
$plan_id = $plan->getID();
|
||||||
|
$cancel_uri = $this->getApplicationURI("plan/{$plan_id}/");
|
||||||
|
|
||||||
if ($request->isDialogFormPost()) {
|
$errors = array();
|
||||||
$class = $request->getStr('step-type');
|
if ($request->isFormPost()) {
|
||||||
|
$class = $request->getStr('class');
|
||||||
if (!HarbormasterBuildStepImplementation::getImplementation($class)) {
|
if (!HarbormasterBuildStepImplementation::getImplementation($class)) {
|
||||||
return $this->createDialog($cancel_uri);
|
$errors[] = pht(
|
||||||
|
'Choose the type of build step you want to add.');
|
||||||
}
|
}
|
||||||
|
if (!$errors) {
|
||||||
$steps = $plan->loadOrderedBuildSteps();
|
$new_uri = $this->getApplicationURI("step/new/{$plan_id}/{$class}/");
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($new_uri);
|
||||||
$step = new HarbormasterBuildStep();
|
|
||||||
$step->setBuildPlanPHID($plan->getPHID());
|
|
||||||
$step->setClassName($class);
|
|
||||||
$step->setDetails(array());
|
|
||||||
$step->setSequence(count($steps) + 1);
|
|
||||||
$step->save();
|
|
||||||
|
|
||||||
$edit_uri = $this->getApplicationURI("step/edit/".$step->getID()."/");
|
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($edit_uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->createDialog($cancel_uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createDialog($cancel_uri) {
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$viewer = $request->getUser();
|
|
||||||
|
|
||||||
$control = id(new AphrontFormRadioButtonControl())
|
$control = id(new AphrontFormRadioButtonControl())
|
||||||
->setName('step-type');
|
->setName('class');
|
||||||
|
|
||||||
$all = HarbormasterBuildStepImplementation::getImplementations();
|
$all = HarbormasterBuildStepImplementation::getImplementations();
|
||||||
foreach ($all as $class => $implementation) {
|
foreach ($all as $class => $implementation) {
|
||||||
|
@ -66,10 +51,16 @@ final class HarbormasterStepAddController
|
||||||
$implementation->getGenericDescription());
|
$implementation->getGenericDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($errors) {
|
||||||
|
$errors = id(new AphrontErrorView())
|
||||||
|
->setErrors($errors);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->newDialog()
|
return $this->newDialog()
|
||||||
->setTitle(pht('Add New Step'))
|
->setTitle(pht('Add New Step'))
|
||||||
->addSubmitButton(pht('Add Build Step'))
|
->addSubmitButton(pht('Add Build Step'))
|
||||||
->addCancelButton($cancel_uri)
|
->addCancelButton($cancel_uri)
|
||||||
|
->appendChild($errors)
|
||||||
->appendParagraph(pht('Choose a type of build step to add:'))
|
->appendParagraph(pht('Choose a type of build step to add:'))
|
||||||
->appendChild($control);
|
->appendChild($control);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,13 @@ final class HarbormasterStepEditController
|
||||||
extends HarbormasterController {
|
extends HarbormasterController {
|
||||||
|
|
||||||
private $id;
|
private $id;
|
||||||
|
private $planID;
|
||||||
|
private $className;
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function willProcessRequest(array $data) {
|
||||||
$this->id = idx($data, 'id');
|
$this->id = idx($data, 'id');
|
||||||
|
$this->planID = idx($data, 'plan');
|
||||||
|
$this->className = idx($data, 'class');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
|
@ -16,6 +20,7 @@ final class HarbormasterStepEditController
|
||||||
$this->requireApplicationCapability(
|
$this->requireApplicationCapability(
|
||||||
HarbormasterCapabilityManagePlans::CAPABILITY);
|
HarbormasterCapabilityManagePlans::CAPABILITY);
|
||||||
|
|
||||||
|
if ($this->id) {
|
||||||
$step = id(new HarbormasterBuildStepQuery())
|
$step = id(new HarbormasterBuildStepQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
@ -23,9 +28,33 @@ final class HarbormasterStepEditController
|
||||||
if (!$step) {
|
if (!$step) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$plan = $step->getBuildPlan();
|
$plan = $step->getBuildPlan();
|
||||||
|
|
||||||
|
$is_new = false;
|
||||||
|
} else {
|
||||||
|
$plan = id(new HarbormasterBuildPlanQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($this->planID))
|
||||||
|
->executeOne();
|
||||||
|
if (!$plan) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$impl = HarbormasterBuildStepImplementation::getImplementation(
|
||||||
|
$this->className);
|
||||||
|
if (!$impl) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$step = HarbormasterBuildStep::initializeNewStep($viewer)
|
||||||
|
->setBuildPlanPHID($plan->getPHID())
|
||||||
|
->setClassName($this->className);
|
||||||
|
|
||||||
|
$is_new = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plan_uri = $this->getApplicationURI('plan/'.$plan->getID().'/');
|
||||||
|
|
||||||
$implementation = $step->getStepImplementation();
|
$implementation = $step->getStepImplementation();
|
||||||
|
|
||||||
$field_list = PhabricatorCustomField::getObjectFields(
|
$field_list = PhabricatorCustomField::getObjectFields(
|
||||||
|
@ -47,10 +76,16 @@ final class HarbormasterStepEditController
|
||||||
->setContinueOnNoEffect(true)
|
->setContinueOnNoEffect(true)
|
||||||
->setContentSourceFromRequest($request);
|
->setContentSourceFromRequest($request);
|
||||||
|
|
||||||
|
if ($is_new) {
|
||||||
|
// This is okay, but a little iffy. We should move it inside the editor
|
||||||
|
// if we create plans elsewhere.
|
||||||
|
$steps = $plan->loadOrderedBuildSteps();
|
||||||
|
$step->setSequence(count($steps) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$editor->applyTransactions($step, $xactions);
|
$editor->applyTransactions($step, $xactions);
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())->setURI($plan_uri);
|
||||||
->setURI($this->getApplicationURI('plan/'.$plan->getID().'/'));
|
|
||||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||||
$validation_exception = $ex;
|
$validation_exception = $ex;
|
||||||
}
|
}
|
||||||
|
@ -61,26 +96,36 @@ final class HarbormasterStepEditController
|
||||||
|
|
||||||
$field_list->appendFieldsToForm($form);
|
$field_list->appendFieldsToForm($form);
|
||||||
|
|
||||||
|
if ($is_new) {
|
||||||
|
$submit = pht('Create Build Step');
|
||||||
|
$header = pht('New Step: %s', $implementation->getName());
|
||||||
|
$crumb = pht('Add Step');
|
||||||
|
} else {
|
||||||
|
$submit = pht('Save Build Step');
|
||||||
|
$header = pht('Edit Step: %s', $implementation->getName());
|
||||||
|
$crumb = pht('Edit Step');
|
||||||
|
}
|
||||||
|
|
||||||
$form->appendChild(
|
$form->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->setValue(pht('Save Build Step'))
|
->setValue($submit)
|
||||||
->addCancelButton(
|
->addCancelButton($plan_uri));
|
||||||
$this->getApplicationURI('plan/'.$plan->getID().'/')));
|
|
||||||
|
|
||||||
$box = id(new PHUIObjectBoxView())
|
$box = id(new PHUIObjectBoxView())
|
||||||
->setHeaderText('Edit Step: '.$implementation->getName())
|
->setHeaderText($header)
|
||||||
->setValidationException($validation_exception)
|
->setValidationException($validation_exception)
|
||||||
->setForm($form);
|
->setForm($form);
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$id = $plan->getID();
|
$id = $plan->getID();
|
||||||
$crumbs->addTextCrumb(
|
$crumbs->addTextCrumb(pht('Plan %d', $id), $plan_uri);
|
||||||
pht("Plan %d", $id),
|
$crumbs->addTextCrumb($crumb);
|
||||||
$this->getApplicationURI("plan/{$id}/"));
|
|
||||||
$crumbs->addTextCrumb(pht('Edit Step'));
|
|
||||||
|
|
||||||
$variables = $this->renderBuildVariablesTable();
|
$variables = $this->renderBuildVariablesTable();
|
||||||
|
|
||||||
|
if ($is_new) {
|
||||||
|
$xaction_view = null;
|
||||||
|
} else {
|
||||||
$xactions = id(new HarbormasterBuildStepTransactionQuery())
|
$xactions = id(new HarbormasterBuildStepTransactionQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withObjectPHIDs(array($step->getPHID()))
|
->withObjectPHIDs(array($step->getPHID()))
|
||||||
|
@ -91,6 +136,7 @@ final class HarbormasterStepEditController
|
||||||
->setObjectPHID($step->getPHID())
|
->setObjectPHID($step->getPHID())
|
||||||
->setTransactions($xactions)
|
->setTransactions($xactions)
|
||||||
->setShouldTerminate(true);
|
->setShouldTerminate(true);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -14,6 +14,10 @@ final class HarbormasterBuildStep extends HarbormasterDAO
|
||||||
private $customFields = self::ATTACHABLE;
|
private $customFields = self::ATTACHABLE;
|
||||||
private $implementation;
|
private $implementation;
|
||||||
|
|
||||||
|
public static function initializeNewStep(PhabricatorUser $actor) {
|
||||||
|
return id(new HarbormasterBuildStep());
|
||||||
|
}
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_AUX_PHID => true,
|
self::CONFIG_AUX_PHID => true,
|
||||||
|
|
Loading…
Reference in a new issue