1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-18 10:41:08 +01:00

Implement all field edit interfaces on the custom field schema

Summary:
Moves the revision edit controller to be completely schema-driven.

Depends on D810.

Test Plan: Edited revisions. Entered intentionally invalid values to trigger
error conditions.
Reviewed By: jungejason
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, jungejason, epriestley
Differential Revision: 810
This commit is contained in:
epriestley 2011-08-14 14:28:08 -07:00
parent 442d1dbeaa
commit a869dbf45b
17 changed files with 337 additions and 79 deletions

View file

@ -207,7 +207,10 @@ phutil_register_library_map(array(
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview', 'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
'DifferentialSubscribeController' => 'applications/differential/controller/subscribe', 'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/summary',
'DifferentialTasksAttacher' => 'applications/differential/tasks', 'DifferentialTasksAttacher' => 'applications/differential/tasks',
'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/testplan',
'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/title',
'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit', 'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit',
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult', 'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult',
@ -845,6 +848,9 @@ phutil_register_library_map(array(
'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSubscribeController' => 'DifferentialController', 'DifferentialSubscribeController' => 'DifferentialController',
'DifferentialSummaryFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialTitleFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialViewTime' => 'DifferentialDAO', 'DifferentialViewTime' => 'DifferentialDAO',
'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBranchTableView' => 'DiffusionView',

View file

@ -41,6 +41,7 @@ class DifferentialRevisionEditController extends DifferentialController {
$revision = new DifferentialRevision(); $revision = new DifferentialRevision();
} }
$revision->loadRelationships();
$aux_fields = $this->loadAuxiliaryFields($revision); $aux_fields = $this->loadAuxiliaryFields($revision);
$diff_id = $request->getInt('diffID'); $diff_id = $request->getInt('diffID');
@ -57,39 +58,12 @@ class DifferentialRevisionEditController extends DifferentialController {
$diff = null; $diff = null;
} }
$e_title = true;
$e_testplan = true;
$e_reviewers = null;
$errors = array(); $errors = array();
$revision->loadRelationships();
if ($request->isFormPost() && !$request->getStr('viaDiffView')) { if ($request->isFormPost() && !$request->getStr('viaDiffView')) {
$revision->setTitle($request->getStr('title'));
$revision->setSummary($request->getStr('summary'));
$revision->setTestPlan($request->getStr('testplan'));
if (!strlen(trim($revision->getTitle()))) {
$errors[] = 'You must provide a title.';
$e_title = 'Required';
} else {
$e_title = null;
}
if (!strlen(trim($revision->getTestPlan()))) {
$errors[] = 'You must provide a test plan.';
$e_testplan = 'Required';
} else {
$e_testplan = null;
}
$user_phid = $request->getUser()->getPHID(); $user_phid = $request->getUser()->getPHID();
if (in_array($user_phid, $request->getArr('reviewers'))) {
$errors[] = 'You may not review your own revision.';
$e_reviewers = 'Invalid';
}
foreach ($aux_fields as $aux_field) { foreach ($aux_fields as $aux_field) {
$aux_field->setValueFromRequest($request); $aux_field->setValueFromRequest($request);
try { try {
@ -105,30 +79,24 @@ class DifferentialRevisionEditController extends DifferentialController {
$editor->addDiff($diff, $request->getStr('comments')); $editor->addDiff($diff, $request->getStr('comments'));
} }
$editor->setAuxiliaryFields($aux_fields); $editor->setAuxiliaryFields($aux_fields);
$editor->setCCPHIDs($request->getArr('cc'));
$editor->setReviewers($request->getArr('reviewers'));
$editor->save(); $editor->save();
return id(new AphrontRedirectResponse()) return id(new AphrontRedirectResponse())
->setURI('/D'.$revision->getID()); ->setURI('/D'.$revision->getID());
} }
$reviewer_phids = $request->getArr('reviewers');
$cc_phids = $request->getArr('cc');
} else {
$reviewer_phids = $revision->getReviewers();
$cc_phids = $revision->getCCPHIDs();
} }
$phids = array_merge($reviewer_phids, $cc_phids); $aux_phids = array();
foreach ($aux_fields as $key => $aux_field) {
$aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionEdit();
}
$phids = array_mergev($aux_phids);
$phids = array_unique($phids); $phids = array_unique($phids);
$handles = id(new PhabricatorObjectHandleData($phids)) $handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles(); ->loadHandles();
$handles = mpull($handles, 'getFullName', 'getPHID'); foreach ($aux_fields as $key => $aux_field) {
$aux_field->setHandles(array_select_keys($handles, $aux_phids[$key]));
$reviewer_map = array_select_keys($handles, $reviewer_phids); }
$cc_map = array_select_keys($handles, $cc_phids);
$form = new AphrontFormView(); $form = new AphrontFormView();
$form->setUser($request->getUser()); $form->setUser($request->getUser());
@ -164,39 +132,6 @@ class DifferentialRevisionEditController extends DifferentialController {
id(new AphrontFormDividerControl())); id(new AphrontFormDividerControl()));
} }
$form
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Title')
->setName('title')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($revision->getTitle())
->setError($e_title))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Summary')
->setName('summary')
->setValue($revision->getSummary()))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Test Plan')
->setName('testplan')
->setValue($revision->getTestPlan())
->setError($e_testplan))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('Reviewers')
->setName('reviewers')
->setDatasource('/typeahead/common/users/')
->setError($e_reviewers)
->setValue($reviewer_map))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('CC')
->setName('cc')
->setDatasource('/typeahead/common/mailable/')
->setValue($cc_map));
foreach ($aux_fields as $aux_field) { foreach ($aux_fields as $aux_field) {
$control = $aux_field->renderEditControl(); $control = $aux_field->renderEditControl();
if ($control) { if ($control) {
@ -237,11 +172,16 @@ class DifferentialRevisionEditController extends DifferentialController {
private function loadAuxiliaryFields(DifferentialRevision $revision) { private function loadAuxiliaryFields(DifferentialRevision $revision) {
$user = $this->getRequest()->getUser();
$aux_fields = DifferentialFieldSelector::newSelector() $aux_fields = DifferentialFieldSelector::newSelector()
->getFieldSpecifications(); ->getFieldSpecifications();
foreach ($aux_fields as $key => $aux_field) { foreach ($aux_fields as $key => $aux_field) {
$aux_field->setRevision($revision);
if (!$aux_field->shouldAppearOnEdit()) { if (!$aux_field->shouldAppearOnEdit()) {
unset($aux_fields[$key]); unset($aux_fields[$key]);
} else {
$aux_field->setUser($user);
} }
} }

View file

@ -19,7 +19,6 @@ phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/divider'); phutil_require_module('phabricator', 'view/form/control/divider');
phutil_require_module('phabricator', 'view/form/control/submit'); phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea'); phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/control/tokenizer');
phutil_require_module('phabricator', 'view/form/error'); phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phabricator', 'view/layout/panel');

View file

@ -672,10 +672,11 @@ class DifferentialRevisionEditor {
$aux_map = array(); $aux_map = array();
foreach ($this->auxiliaryFields as $aux_field) { foreach ($this->auxiliaryFields as $aux_field) {
$key = $aux_field->getStorageKey(); $key = $aux_field->getStorageKey();
if ($key !== null) {
$val = $aux_field->getValueForStorage(); $val = $aux_field->getValueForStorage();
$aux_map[$key] = $val; $aux_map[$key] = $val;
} }
}
if (!$aux_map) { if (!$aux_map) {
return; return;

View file

@ -21,6 +21,9 @@ final class DifferentialDefaultFieldSelector
public function getFieldSpecifications() { public function getFieldSpecifications() {
return array( return array(
new DifferentialTitleFieldSpecification(),
new DifferentialSummaryFieldSpecification(),
new DifferentialTestPlanFieldSpecification(),
new DifferentialRevisionStatusFieldSpecification(), new DifferentialRevisionStatusFieldSpecification(),
new DifferentialAuthorFieldSpecification(), new DifferentialAuthorFieldSpecification(),
new DifferentialReviewersFieldSpecification(), new DifferentialReviewersFieldSpecification(),

View file

@ -21,6 +21,9 @@ phutil_require_module('phabricator', 'applications/differential/field/specificat
phutil_require_module('phabricator', 'applications/differential/field/specification/path'); phutil_require_module('phabricator', 'applications/differential/field/specification/path');
phutil_require_module('phabricator', 'applications/differential/field/specification/reviewers'); phutil_require_module('phabricator', 'applications/differential/field/specification/reviewers');
phutil_require_module('phabricator', 'applications/differential/field/specification/revisionstatus'); phutil_require_module('phabricator', 'applications/differential/field/specification/revisionstatus');
phutil_require_module('phabricator', 'applications/differential/field/specification/summary');
phutil_require_module('phabricator', 'applications/differential/field/specification/testplan');
phutil_require_module('phabricator', 'applications/differential/field/specification/title');
phutil_require_module('phabricator', 'applications/differential/field/specification/unit'); phutil_require_module('phabricator', 'applications/differential/field/specification/unit');

View file

@ -37,6 +37,7 @@ abstract class DifferentialFieldSpecification {
private $diff; private $diff;
private $handles; private $handles;
private $diffProperties; private $diffProperties;
private $user;
/* -( Storage )------------------------------------------------------------ */ /* -( Storage )------------------------------------------------------------ */
@ -321,7 +322,7 @@ abstract class DifferentialFieldSpecification {
* @return list List of PHIDs to load handles for. * @return list List of PHIDs to load handles for.
* @task load * @task load
*/ */
public function getRequiredHandlePHIDsForEdit() { public function getRequiredHandlePHIDsForRevisionEdit() {
return $this->getRequiredHandlePHIDs(); return $this->getRequiredHandlePHIDs();
} }
@ -372,6 +373,14 @@ abstract class DifferentialFieldSpecification {
return $this; return $this;
} }
/**
* @task context
*/
final public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
/** /**
* @task context * @task context
*/ */
@ -392,6 +401,16 @@ abstract class DifferentialFieldSpecification {
return $this->diff; return $this->diff;
} }
/**
* @task context
*/
final protected function getUser() {
if (empty($this->user)) {
throw new DifferentialFieldDataNotAvailableException($this);
}
return $this->user;
}
/** /**
* Get the handle for an object PHID. You must overload * Get the handle for an object PHID. You must overload
* @{method:getRequiredHandlePHIDs} (or a more specific version thereof) * @{method:getRequiredHandlePHIDs} (or a more specific version thereof)

View file

@ -19,6 +19,8 @@
final class DifferentialCCsFieldSpecification final class DifferentialCCsFieldSpecification
extends DifferentialFieldSpecification { extends DifferentialFieldSpecification {
private $ccs;
public function shouldAppearOnRevisionView() { public function shouldAppearOnRevisionView() {
return true; return true;
} }
@ -50,4 +52,34 @@ final class DifferentialCCsFieldSpecification
return $revision->getCCPHIDs(); return $revision->getCCPHIDs();
} }
public function shouldAppearOnEdit() {
$this->ccs = $this->getCCPHIDs();
return true;
}
public function getRequiredHandlePHIDsForRevisionEdit() {
return $this->ccs;
}
public function setValueFromRequest(AphrontRequest $request) {
$this->ccs = $request->getArr('cc');
return $this;
}
public function renderEditControl() {
$cc_map = array();
foreach ($this->ccs as $phid) {
$cc_map[$phid] = $this->getHandle($phid)->getFullName();
}
return id(new AphrontFormTokenizerControl())
->setLabel('CC')
->setName('cc')
->setDatasource('/typeahead/common/mailable/')
->setValue($cc_map);
}
public function willWriteRevision(DifferentialRevisionEditor $editor) {
$editor->setCCPHIDs($this->ccs);
}
} }

View file

@ -7,6 +7,9 @@
phutil_require_module('phabricator', 'applications/differential/field/specification/base'); phutil_require_module('phabricator', 'applications/differential/field/specification/base');
phutil_require_module('phabricator', 'view/form/control/tokenizer');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialCCsFieldSpecification.php'); phutil_require_source('DifferentialCCsFieldSpecification.php');

View file

@ -19,6 +19,9 @@
final class DifferentialReviewersFieldSpecification final class DifferentialReviewersFieldSpecification
extends DifferentialFieldSpecification { extends DifferentialFieldSpecification {
private $reviewers;
private $error;
public function shouldAppearOnRevisionView() { public function shouldAppearOnRevisionView() {
return true; return true;
} }
@ -50,4 +53,44 @@ final class DifferentialReviewersFieldSpecification
return $revision->getReviewers(); return $revision->getReviewers();
} }
public function shouldAppearOnEdit() {
$this->reviewers = $this->getReviewerPHIDs();
return true;
}
public function getRequiredHandlePHIDsForRevisionEdit() {
return $this->reviewers;
}
public function setValueFromRequest(AphrontRequest $request) {
$this->reviewers = $request->getArr('reviewers');
return $this;
}
public function validateField() {
if (in_array($this->getUser()->getPHID(), $this->reviewers)) {
$this->error = 'Invalid';
throw new DifferentialFieldValidationException(
"You may not review your own revision!");
}
}
public function renderEditControl() {
$reviewer_map = array();
foreach ($this->reviewers as $phid) {
$reviewer_map[$phid] = $this->getHandle($phid)->getFullName();
}
return id(new AphrontFormTokenizerControl())
->setLabel('Reviewers')
->setName('reviewers')
->setDatasource('/typeahead/common/users/')
->setValue($reviewer_map)
->setError($this->error);
}
public function willWriteRevision(DifferentialRevisionEditor $editor) {
$editor->setReviewers($this->reviewers);
}
} }

View file

@ -6,7 +6,11 @@
phutil_require_module('phabricator', 'applications/differential/field/exception/validation');
phutil_require_module('phabricator', 'applications/differential/field/specification/base'); phutil_require_module('phabricator', 'applications/differential/field/specification/base');
phutil_require_module('phabricator', 'view/form/control/tokenizer');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialReviewersFieldSpecification.php'); phutil_require_source('DifferentialReviewersFieldSpecification.php');

View file

@ -0,0 +1,45 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DifferentialSummaryFieldSpecification
extends DifferentialFieldSpecification {
private $summary;
public function shouldAppearOnEdit() {
$this->summary = $this->getRevision()->getSummary();
return true;
}
public function setValueFromRequest(AphrontRequest $request) {
$this->summary = $request->getStr('summary');
return $this;
}
public function renderEditControl() {
return id(new AphrontFormTextAreaControl())
->setLabel('Summary')
->setName('summary')
->setValue($this->summary);
}
public function willWriteRevision(DifferentialRevisionEditor $editor) {
$this->getRevision()->setSummary($this->summary);
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/field/specification/base');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialSummaryFieldSpecification.php');

View file

@ -0,0 +1,56 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DifferentialTestPlanFieldSpecification
extends DifferentialFieldSpecification {
private $plan;
private $error = true;
public function shouldAppearOnEdit() {
$this->plan = $this->getRevision()->getTestPlan();
return true;
}
public function setValueFromRequest(AphrontRequest $request) {
$this->plan = $request->getStr('testplan');
$this->error = null;
return $this;
}
public function renderEditControl() {
return id(new AphrontFormTextAreaControl())
->setLabel('Test Plan')
->setName('testplan')
->setValue($this->plan)
->setError($this->error);
}
public function willWriteRevision(DifferentialRevisionEditor $editor) {
$this->getRevision()->setTestPlan($this->plan);
}
public function validateField() {
if (!strlen($this->plan)) {
$this->error = 'Required';
throw new DifferentialFieldValidationException(
"You must provide a test plan.");
}
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/field/exception/validation');
phutil_require_module('phabricator', 'applications/differential/field/specification/base');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialTestPlanFieldSpecification.php');

View file

@ -0,0 +1,57 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class DifferentialTitleFieldSpecification
extends DifferentialFieldSpecification {
private $title;
private $error = true;
public function shouldAppearOnEdit() {
$this->title = $this->getRevision()->getTitle();
return true;
}
public function setValueFromRequest(AphrontRequest $request) {
$this->title = $request->getStr('title');
$this->error = null;
return $this;
}
public function renderEditControl() {
return id(new AphrontFormTextAreaControl())
->setLabel('Title')
->setName('title')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setError($this->error)
->setValue($this->title);
}
public function willWriteRevision(DifferentialRevisionEditor $editor) {
$this->getRevision()->setTitle($this->title);
}
public function validateField() {
if (!strlen($this->title)) {
$this->error = 'Required';
throw new DifferentialFieldValidationException(
"You must provide a title.");
}
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/field/exception/validation');
phutil_require_module('phabricator', 'applications/differential/field/specification/base');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialTitleFieldSpecification.php');