From 53d5cd395077b280c02ef51c069a4e7039a4a3e4 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 18 Nov 2015 10:38:12 -0800 Subject: [PATCH] Allow EditEngine forms to have defaults assigned Summary: Ref T9132. Allow form configurations to include defaults (like default projects, spaces, policies, etc). Test Plan: Defaulted "Language" to "Rainbow", plus other adjustments: {F975746} {F975747} {F975748} {F975749} Reviewers: chad Reviewed By: chad Maniphest Tasks: T9132 Differential Revision: https://secure.phabricator.com/D14508 --- src/__phutil_library_map__.php | 2 + .../PhabricatorTransactionsApplication.php | 2 + ...tEngineConfigurationDefaultsController.php | 111 ++++++++++++++++++ ...rEditEngineConfigurationViewController.php | 12 +- .../editengine/PhabricatorEditEngine.php | 4 + .../editfield/PhabricatorEditField.php | 43 ++++++- ...abricatorEditEngineConfigurationEditor.php | 10 ++ .../PhabricatorEditEngineConfiguration.php | 12 ++ ...atorEditEngineConfigurationTransaction.php | 41 +++++++ 9 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 0f239ea0ad..02f66e7320 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2112,6 +2112,7 @@ phutil_register_library_map(array( 'PhabricatorEditEngine' => 'applications/transactions/editengine/PhabricatorEditEngine.php', 'PhabricatorEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php', 'PhabricatorEditEngineConfiguration' => 'applications/transactions/storage/PhabricatorEditEngineConfiguration.php', + 'PhabricatorEditEngineConfigurationDefaultsController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php', 'PhabricatorEditEngineConfigurationEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php', 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php', 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php', @@ -6205,6 +6206,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), + 'PhabricatorEditEngineConfigurationDefaultsController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor', diff --git a/src/applications/transactions/application/PhabricatorTransactionsApplication.php b/src/applications/transactions/application/PhabricatorTransactionsApplication.php index 1f78c71bd2..9006a91ce3 100644 --- a/src/applications/transactions/application/PhabricatorTransactionsApplication.php +++ b/src/applications/transactions/application/PhabricatorTransactionsApplication.php @@ -47,6 +47,8 @@ final class PhabricatorTransactionsApplication extends PhabricatorApplication { 'PhabricatorEditEngineConfigurationSaveController', 'reorder/(?P[^/]+)/' => 'PhabricatorEditEngineConfigurationReorderController', + 'defaults/(?P[^/]+)/' => + 'PhabricatorEditEngineConfigurationDefaultsController', ), ), ), diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php new file mode 100644 index 0000000000..fa7f30c858 --- /dev/null +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php @@ -0,0 +1,111 @@ +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 id(new Aphront404Response()); + } + + $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/"; + + $engine = $config->getEngine(); + $fields = $engine->getFieldsForConfig($config); + + foreach ($fields as $key => $field) { + if (!$field->getIsDefaultable()) { + unset($fields[$key]); + continue; + } + } + + foreach ($fields as $field) { + $field->setIsEditDefaults(true); + } + + if ($request->isFormPost()) { + $xactions = array(); + + foreach ($fields as $field) { + $field->readValueFromSubmit($request); + } + + $type = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; + + $xactions = array(); + foreach ($fields as $field) { + $new_value = $field->getValueForDefaults(); + $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction()) + ->setTransactionType($type) + ->setMetadataValue('field.key', $field->getKey()) + ->setNewValue($new_value); + } + + $editor = id(new PhabricatorEditEngineConfigurationEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($config, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + $title = pht('Edit Form Defaults'); + + $form = id(new AphrontFormView()) + ->setUser($viewer); + + foreach ($fields as $field) { + $field->appendToForm($form); + } + + $form + ->appendControl( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Save Defaults')) + ->addCancelButton($cancel_uri)); + + $info = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) + ->setErrors( + array( + pht('You are editing the default values for this form.'), + )); + + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText($title) + ->setInfoView($info) + ->setForm($form); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Form %d', $config->getID()), $cancel_uri); + $crumbs->addTextCrumb(pht('Edit Defaults')); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($box); + } + +} diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php index deeed6252a..0dc26c57cd 100644 --- a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php @@ -119,11 +119,21 @@ final class PhabricatorEditEngineConfigurationViewController ->setIcon('fa-th-list') ->setHref($use_uri)); + $defaults_uri = "{$base_uri}/defaults/{$form_key}/"; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Change Default Values')) + ->setIcon('fa-paint-brush') + ->setHref($defaults_uri) + ->setWorkflow(!$can_edit) + ->setDisabled(!$can_edit)); + $reorder_uri = "{$base_uri}/reorder/{$form_key}/"; $view->addAction( id(new PhabricatorActionView()) - ->setName(pht('Reorder Fields')) + ->setName(pht('Change Field Order')) ->setIcon('fa-sort-alpha-asc') ->setHref($reorder_uri) ->setWorkflow(true) diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php index f195664702..e3746f3d7c 100644 --- a/src/applications/transactions/editengine/PhabricatorEditEngine.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php @@ -62,8 +62,12 @@ abstract class PhabricatorEditEngine PhabricatorEditEngineConfiguration $config) { $object = $this->newEditableObject(); + $this->editEngineConfiguration = $config; + // This is mostly making sure that we fill in default values. + $this->setIsCreate(true); + return $this->buildEditFields($object); } diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php index 58a1435c0c..23a9ca7f3b 100644 --- a/src/applications/transactions/editfield/PhabricatorEditField.php +++ b/src/applications/transactions/editfield/PhabricatorEditField.php @@ -16,6 +16,8 @@ abstract class PhabricatorEditField extends Phobject { private $isLocked; private $isPreview; private $isReorderable = true; + private $isEditDefaults; + private $isDefaultable = true; public function setKey($key) { $this->key = $key; @@ -98,6 +100,24 @@ abstract class PhabricatorEditField extends Phobject { return $this->isReorderable; } + public function setIsEditDefaults($is_edit_defaults) { + $this->isEditDefaults = $is_edit_defaults; + return $this; + } + + public function getIsEditDefaults() { + return $this->isEditDefaults; + } + + public function setIsDefaultable($is_defaultable) { + $this->isDefaultable = $is_defaultable; + return $this; + } + + public function getIsDefaultable() { + return $this->isDefaultable; + } + protected function newControl() { throw new PhutilMethodNotImplementedException(); } @@ -116,10 +136,16 @@ abstract class PhabricatorEditField extends Phobject { $control->setLabel($this->getLabel()); } - if ($this->getIsLocked() || $this->getIsPreview()) { - $control->setDisabled(true); + if ($this->getIsPreview()) { + $disabled = true; + } else if ($this->getIsEditDefaults()) { + $disabled = false; + } else { + $disabled = $this->getIsLocked(); } + $control->setDisabled($disabled); + return $control; } @@ -135,6 +161,19 @@ abstract class PhabricatorEditField extends Phobject { return $this->getValue(); } + public function getValueForDefaults() { + $value = $this->getValue(); + + // By default, just treat the empty string like `null` since they're + // equivalent for almost all fields and this reduces the number of + // meaningless transactions we generate when adjusting defaults. + if ($value === '') { + return null; + } + + return $value; + } + protected function getValue() { return $this->value; } diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php index 626e63f852..003c1e1c09 100644 --- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php +++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php @@ -20,6 +20,7 @@ final class PhabricatorEditEngineConfigurationEditor $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_NAME; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; return $types; } @@ -63,6 +64,9 @@ final class PhabricatorEditEngineConfigurationEditor return $object->getPreamble(); case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: return $object->getFieldOrder(); + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + $field_key = $xaction->getMetadataValue('field.key'); + return $object->getFieldDefault($field_key); } } @@ -74,6 +78,7 @@ final class PhabricatorEditEngineConfigurationEditor case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: return $xaction->getNewValue(); } } @@ -92,6 +97,10 @@ final class PhabricatorEditEngineConfigurationEditor case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: $object->setFieldOrder($xaction->getNewValue()); return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + $field_key = $xaction->getMetadataValue('field.key'); + $object->setFieldDefault($field_key, $xaction->getNewValue()); + return; } return parent::applyCustomInternalTransaction($object, $xaction); @@ -105,6 +114,7 @@ final class PhabricatorEditEngineConfigurationEditor case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: return; } diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php index a95375c53e..33964d9fcd 100644 --- a/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php @@ -105,6 +105,7 @@ final class PhabricatorEditEngineConfiguration 'config.preamble' => id(new PhabricatorInstructionsEditField()) ->setKey('config.preamble') ->setIsReorderable(false) + ->setIsDefaultable(false) ->setValue($preamble), ) + $fields; } @@ -175,6 +176,17 @@ final class PhabricatorEditEngineConfiguration return $this->getProperty('order', array()); } + public function getFieldDefault($key) { + $defaults = $this->getProperty('defaults', array()); + return idx($defaults, $key); + } + + public function setFieldDefault($key, $value) { + $defaults = $this->getProperty('defaults', array()); + $defaults[$key] = $value; + return $this->setProperty('defaults', $defaults); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php index 77f5b4ef20..6b7784eb3d 100644 --- a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php @@ -6,6 +6,7 @@ final class PhabricatorEditEngineConfigurationTransaction const TYPE_NAME = 'editengine.config.name'; const TYPE_PREAMBLE = 'editengine.config.preamble'; const TYPE_ORDER = 'editengine.config.order'; + const TYPE_DEFAULT = 'editengine.config.default'; public function getApplicationName() { return 'search'; @@ -19,4 +20,44 @@ final class PhabricatorEditEngineConfigurationTransaction return null; } + public function getTitle() { + $author_phid = $this->getAuthorPHID(); + + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $type = $this->getTransactionType(); + switch ($type) { + case self::TYPE_NAME: + if (strlen($old)) { + return pht( + '%s renamed this form from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $old, + $new); + } else { + return pht( + '%s named this form "%s".', + $this->renderHandleLink($author_phid), + $new); + } + case self::TYPE_PREAMBLE: + return pht( + '%s updated the preamble for this form.', + $this->renderHandleLink($author_phid)); + case self::TYPE_ORDER: + return pht( + '%s reordered the fields in this form.', + $this->renderHandleLink($author_phid)); + case self::TYPE_DEFAULT: + $key = $this->getMetadataValue('field.key'); + return pht( + '%s changed the default value for field "%s".', + $this->renderHandleLink($author_phid), + $key); + } + + return parent::getTitle(); + } + }