1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-30 02:32:42 +01:00

Allow EditEngine forms for objects which support subtyping to have a subtype configured

Summary:
Ref T12314. This adds a "Change Form Subtype" workflow to the EditEngine form configuration screen, for forms that edit/create objects which support subtyping (for now, only tasks).

For example, this allows you to switch a form from being a "task" form to a "plant" or "animal" form.

Doing this doesn't yet do anything useful or interesting. I'm also not showing it in the UI yet since I'm not sure what we should make that look like (presumably, we should just echo whatever UI we end up with on tasks).

Test Plan:
  - Changed the subtype of a task form.
  - Verified that the "Change Subtype" action doesn't appear on other forms (for example, those for Pastes).

{F3491374}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12314

Differential Revision: https://secure.phabricator.com/D17442
This commit is contained in:
epriestley 2017-03-01 16:04:25 -08:00
parent dc7ecf5875
commit b9d60d2653
10 changed files with 198 additions and 0 deletions

View file

@ -2610,6 +2610,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationSaveController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php', 'PhabricatorEditEngineConfigurationSaveController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php',
'PhabricatorEditEngineConfigurationSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php', 'PhabricatorEditEngineConfigurationSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php',
'PhabricatorEditEngineConfigurationSortController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSortController.php', 'PhabricatorEditEngineConfigurationSortController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSortController.php',
'PhabricatorEditEngineConfigurationSubtypeController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSubtypeController.php',
'PhabricatorEditEngineConfigurationTransaction' => 'applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php', 'PhabricatorEditEngineConfigurationTransaction' => 'applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php',
'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php', 'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php',
'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php', 'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php',
@ -7669,6 +7670,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationSaveController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSaveController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineConfigurationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorEditEngineConfigurationSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorEditEngineConfigurationSortController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSortController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineConfigurationSubtypeController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController',

View file

@ -557,4 +557,9 @@ final class ManiphestTask extends ManiphestDAO
return $this->setSubtype($value); return $this->setSubtype($value);
} }
public function newEditEngineSubtypeMap() {
$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');
return PhabricatorEditEngineSubtype::newSubtypeMap($config);
}
} }

View file

@ -55,6 +55,8 @@ final class PhabricatorTransactionsApplication extends PhabricatorApplication {
'PhabricatorEditEngineConfigurationDefaultsController', 'PhabricatorEditEngineConfigurationDefaultsController',
'lock/(?P<key>[^/]+)/' => 'lock/(?P<key>[^/]+)/' =>
'PhabricatorEditEngineConfigurationLockController', 'PhabricatorEditEngineConfigurationLockController',
'subtype/(?P<key>[^/]+)/' =>
'PhabricatorEditEngineConfigurationSubtypeController',
'defaultcreate/(?P<key>[^/]+)/' => 'defaultcreate/(?P<key>[^/]+)/' =>
'PhabricatorEditEngineConfigurationDefaultCreateController', 'PhabricatorEditEngineConfigurationDefaultCreateController',
'defaultedit/(?P<key>[^/]+)/' => 'defaultedit/(?P<key>[^/]+)/' =>

View file

@ -0,0 +1,85 @@
<?php
final class PhabricatorEditEngineConfigurationSubtypeController
extends PhabricatorEditEngineController {
public function handleRequest(AphrontRequest $request) {
$engine_key = $request->getURIData('engineKey');
$this->setEngineKey($engine_key);
$key = $request->getURIData('key');
$viewer = $this->getViewer();
$config = id(new PhabricatorEditEngineConfigurationQuery())
->setViewer($viewer)
->withEngineKeys(array($engine_key))
->withIdentifiers(array($key))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$config) {
return new Aphront404Response();
}
$cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/";
$engine = $config->getEngine();
if (!$engine->supportsSubtypes()) {
return new Aphront404Response();
}
if ($request->isFormPost()) {
$xactions = array();
$subtype = $request->getStr('subtype');
$type_subtype =
PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE;
$xactions[] = id(new PhabricatorEditEngineConfigurationTransaction())
->setTransactionType($type_subtype)
->setNewValue($subtype);
$editor = id(new PhabricatorEditEngineConfigurationEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true);
$editor->applyTransactions($config, $xactions);
return id(new AphrontRedirectResponse())
->setURI($cancel_uri);
}
$fields = $engine->getFieldsForConfig($config);
$help = pht(<<<EOTEXT
Choose the object **subtype** that this form should create and edit.
EOTEXT
);
$map = $engine->newSubtypeMap();
$map = mpull($map, 'getName');
$form = id(new AphrontFormView())
->setUser($viewer)
->appendRemarkupInstructions($help)
->appendControl(
id(new AphrontFormSelectControl())
->setName('subtype')
->setLabel(pht('Subtype'))
->setValue($config->getSubtype())
->setOptions($map));
return $this->newDialog()
->setTitle(pht('Change Form Subtype'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->appendForm($form)
->addSubmitButton(pht('Save Changes'))
->addCancelButton($cancel_uri);
}
}

View file

@ -151,6 +151,27 @@ final class PhabricatorEditEngineConfigurationViewController
->setWorkflow(true) ->setWorkflow(true)
->setDisabled(!$can_edit)); ->setDisabled(!$can_edit));
if ($engine->supportsSubtypes()) {
$subtype_uri = "{$base_uri}/subtype/{$form_key}/";
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Change Form Subtype'))
->setIcon('fa-drivers-license-o')
->setHref($subtype_uri)
->setWorkflow(true)
->setDisabled(!$can_edit));
}
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Change Default Values'))
->setIcon('fa-paint-brush')
->setHref($defaults_uri)
->setWorkflow(!$can_edit)
->setDisabled(!$can_edit));
$disable_uri = "{$base_uri}/disable/{$form_key}/"; $disable_uri = "{$base_uri}/disable/{$form_key}/";
if ($config->getIsDisabled()) { if ($config->getIsDisabled()) {

View file

@ -213,6 +213,20 @@ abstract class PhabricatorEditEngine
return $fields; return $fields;
} }
final public function supportsSubtypes() {
try {
$object = $this->newEditableObject();
} catch (Exception $ex) {
return false;
}
return ($object instanceof PhabricatorEditEngineSubtypeInterface);
}
final public function newSubtypeMap() {
return $this->newEditableObject()->newEditEngineSubtypeMap();
}
/* -( Display Text )------------------------------------------------------- */ /* -( Display Text )------------------------------------------------------- */

View file

@ -6,6 +6,27 @@ final class PhabricatorEditEngineSubtype
const SUBTYPE_DEFAULT = 'default'; const SUBTYPE_DEFAULT = 'default';
private $key;
private $name;
public function setKey($key) {
$this->key = $key;
return $this;
}
public function getKey() {
return $this->key;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public static function validateSubtypeKey($subtype) { public static function validateSubtypeKey($subtype) {
if (strlen($subtype) > 64) { if (strlen($subtype) > 64) {
throw new Exception( throw new Exception(
@ -81,4 +102,19 @@ final class PhabricatorEditEngineSubtype
} }
} }
public static function newSubtypeMap(array $config) {
$map = array();
foreach ($config as $entry) {
$key = $entry['key'];
$name = $entry['name'];
$map[$key] = id(new self())
->setKey($key)
->setName($name);
}
return $map;
}
} }

View file

@ -4,5 +4,6 @@ interface PhabricatorEditEngineSubtypeInterface {
public function getEditEngineSubtype(); public function getEditEngineSubtype();
public function setEditEngineSubtype($subtype); public function setEditEngineSubtype($subtype);
public function newEditEngineSubtypeMap();
} }

View file

@ -21,6 +21,7 @@ final class PhabricatorEditEngineConfigurationEditor
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE;
$types[] = $types[] =
PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE; PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT;
@ -55,6 +56,22 @@ final class PhabricatorEditEngineConfigurationEditor
$errors[] = $error; $errors[] = $error;
} }
break; break;
case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE:
$map = $object->getEngine()->newSubtypeMap();
foreach ($xactions as $xaction) {
$new = $xaction->getNewValue();
if (isset($map[$new])) {
continue;
}
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('Subtype "%s" is not a valid subtype.', $new),
$xaction);
}
break;
} }
return $errors; return $errors;
@ -76,6 +93,8 @@ final class PhabricatorEditEngineConfigurationEditor
return $object->getFieldDefault($field_key); return $object->getFieldDefault($field_key);
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
return $object->getFieldLocks(); return $object->getFieldLocks();
case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE:
return $object->getSubtype();
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE:
return (int)$object->getIsDefault(); return (int)$object->getIsDefault();
case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT:
@ -86,6 +105,7 @@ final class PhabricatorEditEngineConfigurationEditor
return (int)$object->getCreateOrder(); return (int)$object->getCreateOrder();
case PhabricatorEditEngineConfigurationTransaction::TYPE_EDITORDER: case PhabricatorEditEngineConfigurationTransaction::TYPE_EDITORDER:
return (int)$object->getEditOrder(); return (int)$object->getEditOrder();
} }
} }
@ -99,6 +119,7 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER:
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE:
return $xaction->getNewValue(); return $xaction->getNewValue();
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE:
case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT:
@ -130,6 +151,9 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
$object->setFieldLocks($xaction->getNewValue()); $object->setFieldLocks($xaction->getNewValue());
return; return;
case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE:
$object->setSubtype($xaction->getNewValue());
return;
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE:
$object->setIsDefault($xaction->getNewValue()); $object->setIsDefault($xaction->getNewValue());
return; return;
@ -161,6 +185,7 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT:
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE:
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE:
case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE:
case PhabricatorEditEngineConfigurationTransaction::TYPE_CREATEORDER: case PhabricatorEditEngineConfigurationTransaction::TYPE_CREATEORDER:

View file

@ -13,6 +13,7 @@ final class PhabricatorEditEngineConfigurationTransaction
const TYPE_DISABLE = 'editengine.config.disable'; const TYPE_DISABLE = 'editengine.config.disable';
const TYPE_CREATEORDER = 'editengine.order.create'; const TYPE_CREATEORDER = 'editengine.order.create';
const TYPE_EDITORDER = 'editengine.order.edit'; const TYPE_EDITORDER = 'editengine.order.edit';
const TYPE_SUBTYPE = 'editengine.config.subtype';
public function getApplicationName() { public function getApplicationName() {
return 'search'; return 'search';
@ -99,6 +100,12 @@ final class PhabricatorEditEngineConfigurationTransaction
'%s enabled this form.', '%s enabled this form.',
$this->renderHandleLink($author_phid)); $this->renderHandleLink($author_phid));
} }
case self::TYPE_SUBTYPE:
return pht(
'%s changed the subtype of this form from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
} }
return parent::getTitle(); return parent::getTitle();