From 8a0dfa94d43870a980e6d0f5c6a62cab0968537f Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 17 Dec 2015 09:01:58 -0800 Subject: [PATCH] Make configured and EditEngine defaults work correctly for custom fields Summary: Ref T10004. Fixes T5158. There was a long-standing issue with defaults not working properly, but EditEngine has made it more obvious because it's a lot easier to set defaults now. The issue is basically that the defaults are getting set as the field's real value early on, so when we go to generate the transaction "old value" later, we build a transaction that uses the //new// value as both the "new value" and "old value". Then the engine says "you didn't change anything, so I'm going to ignore this" and drops it. To fix this, return `null` as the "old value" by default, and add a call to overwrite that after we load a legitimate old value. This fix is a touch iffy, but I have some grand plans to clean up the CustomField stuff more broadly later on. Test Plan: - Set config defaults on select/typeahead fields, created and edited tasks. - Set form defaults on select/typehaead fields, created and edited tasks. - In all cases, transactions and state accurately reflected edits. - Set defaults on //hidden// fields, verified forms respected them correctly. - This does generate some fluffy transactions, but I'll deal with those in T7661. Reviewers: chad Reviewed By: chad Maniphest Tasks: T5158, T10004 Differential Revision: https://secure.phabricator.com/D14809 --- .../customfield/field/PhabricatorCustomField.php | 7 +++++++ .../field/PhabricatorCustomFieldList.php | 2 ++ .../standard/PhabricatorStandardCustomField.php | 14 ++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index 8b4c167d6d..6299cc047e 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -594,6 +594,13 @@ abstract class PhabricatorCustomField extends Phobject { throw new PhabricatorCustomFieldImplementationIncompleteException($this); } + public function didSetValueFromStorage() { + if ($this->proxy) { + return $this->proxy->didSetValueFromStorage(); + } + return $this; + } + /* -( ApplicationSearch )-------------------------------------------------- */ diff --git a/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php b/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php index 160a618397..9fefa52ad4 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php @@ -73,10 +73,12 @@ final class PhabricatorCustomFieldList extends Phobject { $storage = idx($objects, $key); if ($storage) { $field->setValueFromStorage($storage->getFieldValue()); + $field->didSetValueFromStorage(); } else if ($object->getPHID()) { // NOTE: We set this only if the object exists. Otherwise, we allow the // field to retain any default value it may have. $field->setValueFromStorage(null); + $field->didSetValueFromStorage(); } } diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index a63f32addd..89a4722d85 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -16,6 +16,7 @@ abstract class PhabricatorStandardCustomField private $required; private $default; private $isCopyable; + private $hasStorageValue; abstract public function getFieldType(); @@ -215,6 +216,19 @@ abstract class PhabricatorStandardCustomField return $this->setFieldValue($value); } + public function didSetValueFromStorage() { + $this->hasStorageValue = true; + return $this; + } + + public function getOldValueForApplicationTransactions() { + if ($this->hasStorageValue) { + return $this->getValueForStorage(); + } else { + return null; + } + } + public function shouldAppearInApplicationTransactions() { return true; }