From 029b1b6733948efc19e1878b5bbc88a9eedac0bf Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 29 Nov 2015 10:47:16 -0800 Subject: [PATCH] Partially support CustomFields in EditEngine Summary: Ref T9132. This isn't perfect, but doesn't break any existing functionality. This stuff works: - Editing values. - Reordering fields. - All builtin field tyepes. This stuff may not work yet: - Assigning custom field defaults. - Some conduit stuff. - Fully custom fields? - Locking/hiding fields? Didn't actually test this one. I'll keep chipping away at that stuff. In some cases, it may be easier to convert all the CustomField apps first, although Differential might be a fair bit of work. Test Plan: Created a bunch of custom fields of every avialable type and edited them. {F1008789} Reviewers: chad Reviewed By: chad Maniphest Tasks: T9132 Differential Revision: https://secure.phabricator.com/D14617 --- src/__phutil_library_map__.php | 6 ++ .../editfield/PhabricatorEditField.php | 38 ++++++---- ...bricatorCustomFieldEditEngineExtension.php | 50 +++++++++++++ .../PhabricatorCustomFieldEditField.php | 73 +++++++++++++++++++ .../editor/PhabricatorCustomFieldEditType.php | 53 ++++++++++++++ .../field/PhabricatorCustomField.php | 27 +++++++ .../PhabricatorStandardCustomField.php | 7 ++ 7 files changed, 239 insertions(+), 15 deletions(-) create mode 100644 src/infrastructure/customfield/editor/PhabricatorCustomFieldEditEngineExtension.php create mode 100644 src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php create mode 100644 src/infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index b066e65b06..2da6090204 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1979,6 +1979,9 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldAttachment' => 'infrastructure/customfield/field/PhabricatorCustomFieldAttachment.php', 'PhabricatorCustomFieldConfigOptionType' => 'infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php', 'PhabricatorCustomFieldDataNotAvailableException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldDataNotAvailableException.php', + 'PhabricatorCustomFieldEditEngineExtension' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditEngineExtension.php', + 'PhabricatorCustomFieldEditField' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php', + 'PhabricatorCustomFieldEditType' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php', 'PhabricatorCustomFieldHeraldField' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldField.php', 'PhabricatorCustomFieldHeraldFieldGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldFieldGroup.php', 'PhabricatorCustomFieldImplementationIncompleteException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldImplementationIncompleteException.php', @@ -6065,6 +6068,9 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldAttachment' => 'Phobject', 'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType', 'PhabricatorCustomFieldDataNotAvailableException' => 'Exception', + 'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension', + 'PhabricatorCustomFieldEditField' => 'PhabricatorEditField', + 'PhabricatorCustomFieldEditType' => 'PhabricatorEditType', 'PhabricatorCustomFieldHeraldField' => 'HeraldField', 'PhabricatorCustomFieldHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception', diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php index c4f3227e9e..c4d7494c5b 100644 --- a/src/applications/transactions/editfield/PhabricatorEditField.php +++ b/src/applications/transactions/editfield/PhabricatorEditField.php @@ -145,10 +145,6 @@ abstract class PhabricatorEditField extends Phobject { return $this->isHidden; } - protected function newControl() { - throw new PhutilMethodNotImplementedException(); - } - public function setIsSubmittedForm($is_submitted) { $this->isSubmittedForm = $is_submitted; return $this; @@ -176,7 +172,11 @@ abstract class PhabricatorEditField extends Phobject { return $this->controlError; } - protected function renderControl() { + protected function newControl() { + throw new PhutilMethodNotImplementedException(); + } + + protected function buildControl() { $control = $this->newControl(); if ($control === null) { return null; @@ -190,6 +190,24 @@ abstract class PhabricatorEditField extends Phobject { $control->setLabel($this->getLabel()); } + if ($this->getIsSubmittedForm()) { + $error = $this->getControlError(); + if ($error !== null) { + $control->setError($error); + } + } else if ($this->getIsRequired()) { + $control->setError(true); + } + + return $control; + } + + protected function renderControl() { + $control = $this->buildControl(); + if ($control === null) { + return null; + } + if ($this->getIsPreview()) { $disabled = true; $hidden = false; @@ -207,16 +225,6 @@ abstract class PhabricatorEditField extends Phobject { $control->setDisabled($disabled); - - if ($this->getIsSubmittedForm()) { - $error = $this->getControlError(); - if ($error !== null) { - $control->setError($error); - } - } else if ($this->getIsRequired()) { - $control->setError(true); - } - return $control; } diff --git a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditEngineExtension.php b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditEngineExtension.php new file mode 100644 index 0000000000..2ae4f56d3c --- /dev/null +++ b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditEngineExtension.php @@ -0,0 +1,50 @@ +getViewer(); + + $field_list = PhabricatorCustomField::getObjectFields( + $object, + PhabricatorCustomField::ROLE_EDIT); + + $field_list->setViewer($viewer); + $field_list->readFieldsFromStorage($object); + + $results = array(); + foreach ($field_list->getFields() as $field) { + $edit_fields = $field->getEditEngineFields($engine); + foreach ($edit_fields as $edit_field) { + $results[] = $edit_field; + } + } + + return $results; + } + +} diff --git a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php new file mode 100644 index 0000000000..00dd8f3895 --- /dev/null +++ b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php @@ -0,0 +1,73 @@ +customField = $custom_field; + return $this; + } + + public function getCustomField() { + return $this->customField; + } + + protected function buildControl() { + $field = $this->getCustomField(); + $clone = clone $field; + + if ($this->getIsSubmittedForm()) { + $value = $this->getValue(); + $clone->setValueFromApplicationTransactions($value); + } + + return $clone->renderEditControl(array()); + } + + protected function newEditType() { + return id(new PhabricatorCustomFieldEditType()) + ->setCustomField($this->getCustomField()); + } + + public function getValueForTransaction() { + $value = $this->getValue(); + $field = $this->getCustomField(); + + // Avoid changing the value of the field itself, since later calls would + // incorrectly reflect the new value. + $clone = clone $field; + $clone->setValueFromApplicationTransactions($value); + return $clone->getNewValueForApplicationTransactions(); + } + + protected function getValueExistsInRequest(AphrontRequest $request, $key) { + // For now, never read these out of the request. + return false; + } + + protected function getValueExistsInSubmit(AphrontRequest $request, $key) { + return true; + } + + protected function getValueFromSubmit(AphrontRequest $request, $key) { + $field = $this->getCustomField(); + + $clone = clone $field; + + $clone->readValueFromRequest($request); + return $clone->getNewValueForApplicationTransactions(); + } + + public function getConduitEditTypes() { + // TODO: For now, don't support custom fields over Conduit. + return array(); + } + + protected function newHTTPParameterType() { + // TODO: For now, don't support custom fields for HTTP prefill. + return null; + } + +} diff --git a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php new file mode 100644 index 0000000000..034f939254 --- /dev/null +++ b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php @@ -0,0 +1,53 @@ +customField = $custom_field; + return $this; + } + + public function getCustomField() { + return $this->customField; + } + + public function getValueType() { + // TODO: Improve. + return 'custom'; + } + + public function getMetadata() { + $field = $this->getCustomField(); + return parent::getMetadata() + $field->getApplicationTransactionMetadata(); + } + + public function getValueDescription() { + $field = $this->getCustomField(); + return $field->getFieldDescription(); + } + + public function generateTransactions( + PhabricatorApplicationTransaction $template, + array $spec) { + + $value = idx($spec, 'value'); + + $xaction = $this->newTransaction($template) + ->setNewValue($value); + + $custom_type = PhabricatorTransactions::TYPE_CUSTOMFIELD; + if ($xaction->getTransactionType() == $custom_type) { + $field = $this->getCustomField(); + + $xaction + ->setOldValue($field->getOldValueForApplicationTransactions()) + ->setMetadataValue('customfield:key', $field->getFieldKey()); + } + + return array($xaction); + } + +} diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index 64639ed34f..8fd071092d 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -1082,6 +1082,33 @@ abstract class PhabricatorCustomField extends Phobject { /* -( Edit View )---------------------------------------------------------- */ + public function getEditEngineFields(PhabricatorEditEngine $engine) { + $field = $this->newStandardEditField($engine); + + return array( + $field, + ); + } + + protected function newEditField() { + return id(new PhabricatorCustomFieldEditField()) + ->setCustomField($this); + } + + protected function newStandardEditField() { + if ($this->proxy) { + return $this->proxy->newStandardEditField(); + } + + return $this->newEditField() + ->setKey($this->getFieldKey()) + ->setEditTypeKey('custom.'.$this->getFieldKey()) + ->setLabel($this->getFieldName()) + ->setDescription($this->getFieldDescription()) + ->setTransactionType($this->getApplicationTransactionType()) + ->setValue($this->getNewValueForApplicationTransactions()); + } + /** * @task edit */ diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index ac3e163f6a..66f85bd04d 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -426,4 +426,11 @@ abstract class PhabricatorStandardCustomField } } + protected function newStandardEditField() { + $short = 'custom.'.$this->getRawStandardFieldKey(); + + return parent::newStandardEditField() + ->setEditTypeKey($short); + } + }