mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-19 13:22:42 +01:00
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
This commit is contained in:
parent
a407b83dc2
commit
029b1b6733
7 changed files with 239 additions and 15 deletions
|
@ -1979,6 +1979,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCustomFieldAttachment' => 'infrastructure/customfield/field/PhabricatorCustomFieldAttachment.php',
|
'PhabricatorCustomFieldAttachment' => 'infrastructure/customfield/field/PhabricatorCustomFieldAttachment.php',
|
||||||
'PhabricatorCustomFieldConfigOptionType' => 'infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php',
|
'PhabricatorCustomFieldConfigOptionType' => 'infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php',
|
||||||
'PhabricatorCustomFieldDataNotAvailableException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldDataNotAvailableException.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',
|
'PhabricatorCustomFieldHeraldField' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldField.php',
|
||||||
'PhabricatorCustomFieldHeraldFieldGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldFieldGroup.php',
|
'PhabricatorCustomFieldHeraldFieldGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldFieldGroup.php',
|
||||||
'PhabricatorCustomFieldImplementationIncompleteException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldImplementationIncompleteException.php',
|
'PhabricatorCustomFieldImplementationIncompleteException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldImplementationIncompleteException.php',
|
||||||
|
@ -6065,6 +6068,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorCustomFieldAttachment' => 'Phobject',
|
'PhabricatorCustomFieldAttachment' => 'Phobject',
|
||||||
'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType',
|
'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType',
|
||||||
'PhabricatorCustomFieldDataNotAvailableException' => 'Exception',
|
'PhabricatorCustomFieldDataNotAvailableException' => 'Exception',
|
||||||
|
'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||||
|
'PhabricatorCustomFieldEditField' => 'PhabricatorEditField',
|
||||||
|
'PhabricatorCustomFieldEditType' => 'PhabricatorEditType',
|
||||||
'PhabricatorCustomFieldHeraldField' => 'HeraldField',
|
'PhabricatorCustomFieldHeraldField' => 'HeraldField',
|
||||||
'PhabricatorCustomFieldHeraldFieldGroup' => 'HeraldFieldGroup',
|
'PhabricatorCustomFieldHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||||
'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception',
|
'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception',
|
||||||
|
|
|
@ -145,10 +145,6 @@ abstract class PhabricatorEditField extends Phobject {
|
||||||
return $this->isHidden;
|
return $this->isHidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function newControl() {
|
|
||||||
throw new PhutilMethodNotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIsSubmittedForm($is_submitted) {
|
public function setIsSubmittedForm($is_submitted) {
|
||||||
$this->isSubmittedForm = $is_submitted;
|
$this->isSubmittedForm = $is_submitted;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -176,7 +172,11 @@ abstract class PhabricatorEditField extends Phobject {
|
||||||
return $this->controlError;
|
return $this->controlError;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderControl() {
|
protected function newControl() {
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildControl() {
|
||||||
$control = $this->newControl();
|
$control = $this->newControl();
|
||||||
if ($control === null) {
|
if ($control === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -190,6 +190,24 @@ abstract class PhabricatorEditField extends Phobject {
|
||||||
$control->setLabel($this->getLabel());
|
$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()) {
|
if ($this->getIsPreview()) {
|
||||||
$disabled = true;
|
$disabled = true;
|
||||||
$hidden = false;
|
$hidden = false;
|
||||||
|
@ -207,16 +225,6 @@ abstract class PhabricatorEditField extends Phobject {
|
||||||
|
|
||||||
$control->setDisabled($disabled);
|
$control->setDisabled($disabled);
|
||||||
|
|
||||||
|
|
||||||
if ($this->getIsSubmittedForm()) {
|
|
||||||
$error = $this->getControlError();
|
|
||||||
if ($error !== null) {
|
|
||||||
$control->setError($error);
|
|
||||||
}
|
|
||||||
} else if ($this->getIsRequired()) {
|
|
||||||
$control->setError(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $control;
|
return $control;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCustomFieldEditEngineExtension
|
||||||
|
extends PhabricatorEditEngineExtension {
|
||||||
|
|
||||||
|
const EXTENSIONKEY = 'customfield.fields';
|
||||||
|
|
||||||
|
public function getExtensionPriority() {
|
||||||
|
return 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isExtensionEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExtensionName() {
|
||||||
|
return pht('Custom Fields');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsObject(
|
||||||
|
PhabricatorEditEngine $engine,
|
||||||
|
PhabricatorApplicationTransactionInterface $object) {
|
||||||
|
return ($object instanceof PhabricatorCustomFieldInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildCustomEditFields(
|
||||||
|
PhabricatorEditEngine $engine,
|
||||||
|
PhabricatorApplicationTransactionInterface $object) {
|
||||||
|
|
||||||
|
$viewer = $this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCustomFieldEditField
|
||||||
|
extends PhabricatorEditField {
|
||||||
|
|
||||||
|
private $customField;
|
||||||
|
|
||||||
|
public function setCustomField(PhabricatorCustomField $custom_field) {
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorCustomFieldEditType
|
||||||
|
extends PhabricatorEditType {
|
||||||
|
|
||||||
|
private $customField;
|
||||||
|
|
||||||
|
public function setCustomField(PhabricatorCustomField $custom_field) {
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1082,6 +1082,33 @@ abstract class PhabricatorCustomField extends Phobject {
|
||||||
/* -( Edit View )---------------------------------------------------------- */
|
/* -( 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
|
* @task edit
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -426,4 +426,11 @@ abstract class PhabricatorStandardCustomField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function newStandardEditField() {
|
||||||
|
$short = 'custom.'.$this->getRawStandardFieldKey();
|
||||||
|
|
||||||
|
return parent::newStandardEditField()
|
||||||
|
->setEditTypeKey($short);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue