From 01572d9d933bdf47455dd176f3d3cce35fd85f98 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 21 Feb 2014 11:53:37 -0800 Subject: [PATCH] Implement "Repository" as a new-style CustomField in Differential Summary: Ref T3886. Ref T418. - Adds new capabilities for CustomField: - Controls can now bulk-load PHIDs (e.g., for tokenizers). - Transactions can now bulk-load PHIDs (e.g., for relationship changes). - Implements "Repository" control. - Improves tokenizer StandardCustomField controls. Test Plan: {F115942} {F115943} Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T418, T3886 Differential Revision: https://secure.phabricator.com/D8286 --- src/__phutil_library_map__.php | 2 + .../DifferentialRepositoryField.php | 128 ++++++++++++++++++ .../customfield/DifferentialSummaryField.php | 2 +- .../customfield/DifferentialTestPlanField.php | 2 +- .../customfield/DifferentialTitleField.php | 2 +- .../storage/DifferentialRevision.php | 2 + .../ManiphestTaskEditController.php | 7 +- .../customfield/PhabricatorUserBlurbField.php | 2 +- .../PhabricatorUserRealNameField.php | 2 +- .../customfield/PhabricatorUserTitleField.php | 2 +- .../ReleephLevelFieldSpecification.php | 2 +- .../ReleephReasonFieldSpecification.php | 2 +- .../ReleephSummaryFieldSpecification.php | 2 +- ...PhabricatorApplicationTransactionQuery.php | 46 ++++--- .../PhabricatorApplicationTransaction.php | 7 + .../field/PhabricatorCustomField.php | 24 +++- .../field/PhabricatorCustomFieldList.php | 25 +++- .../PhabricatorStandardCustomField.php | 2 +- .../PhabricatorStandardCustomFieldBool.php | 2 +- .../PhabricatorStandardCustomFieldDate.php | 2 +- .../PhabricatorStandardCustomFieldHeader.php | 2 +- .../PhabricatorStandardCustomFieldPHIDs.php | 71 ++++++++++ ...PhabricatorStandardCustomFieldRemarkup.php | 2 +- .../PhabricatorStandardCustomFieldSelect.php | 2 +- .../PhabricatorStandardCustomFieldUsers.php | 29 +--- 25 files changed, 303 insertions(+), 68 deletions(-) create mode 100644 src/applications/differential/customfield/DifferentialRepositoryField.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 763e124e66..2ff259ee0c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -431,6 +431,7 @@ phutil_register_library_map(array( 'DifferentialReleephRequestFieldSpecification' => 'applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php', 'DifferentialRemarkupRule' => 'applications/differential/remarkup/DifferentialRemarkupRule.php', 'DifferentialReplyHandler' => 'applications/differential/mail/DifferentialReplyHandler.php', + 'DifferentialRepositoryField' => 'applications/differential/customfield/DifferentialRepositoryField.php', 'DifferentialRepositoryFieldSpecification' => 'applications/differential/field/specification/DifferentialRepositoryFieldSpecification.php', 'DifferentialRepositoryLookup' => 'applications/differential/query/DifferentialRepositoryLookup.php', 'DifferentialResultsTableView' => 'applications/differential/view/DifferentialResultsTableView.php', @@ -2967,6 +2968,7 @@ phutil_register_library_map(array( 'DifferentialReleephRequestFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRemarkupRule' => 'PhabricatorRemarkupRuleObject', 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', + 'DifferentialRepositoryField' => 'DifferentialCoreCustomField', 'DifferentialRepositoryFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRepositoryLookup' => 'Phobject', 'DifferentialResultsTableView' => 'AphrontView', diff --git a/src/applications/differential/customfield/DifferentialRepositoryField.php b/src/applications/differential/customfield/DifferentialRepositoryField.php new file mode 100644 index 0000000000..789862b7be --- /dev/null +++ b/src/applications/differential/customfield/DifferentialRepositoryField.php @@ -0,0 +1,128 @@ +getRepositoryPHID(); + } + + protected function writeValueToRevision( + DifferentialRevision $revision, + $value) { + $revision->setRepositoryPHID($value); + } + + public function readValueFromRequest(AphrontRequest $request) { + $phids = $request->getArr($this->getFieldKey()); + $first = head($phids); + $this->setValue(coalesce($first, null)); + } + + public function getRequiredHandlePHIDsForEdit() { + $phids = array(); + if ($this->getValue()) { + $phids[] = $this->getValue(); + } + return $phids; + } + + public function renderEditControl(array $handles) { + + if ($this->getValue()) { + $control_value = array_select_keys($handles, array($this->getValue())); + } else { + $control_value = array(); + } + + return id(new AphrontFormTokenizerControl()) + ->setName($this->getFieldKey()) + ->setDatasource('/typeahead/common/repositories/') + ->setValue($control_value) + ->setError($this->getFieldError()) + ->setLabel($this->getFieldName()) + ->setLimit(1); + } + + public function getApplicationTransactionRequiredHandlePHIDs( + PhabricatorApplicationTransaction $xaction) { + + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + + $phids = array(); + if ($old) { + $phids[] = $old; + } + if ($new) { + $phids[] = $new; + } + + return $phids; + } + + public function getApplicationTransactionTitle( + PhabricatorApplicationTransaction $xaction) { + $author_phid = $xaction->getAuthorPHID(); + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + + if ($old && $new) { + return pht( + '%s changed the repository for this revision from %s to %s.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($old), + $xaction->renderHandleLink($new)); + } else if ($new) { + return pht( + '%s set the repository for this revision to %s.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($new)); + } else { + return pht( + '%s removed %s as the repository for this revision.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($old)); + } + + } + + public function getApplicationTransactionTitleForFeed( + PhabricatorApplicationTransaction $xaction, + PhabricatorFeedStory $story) { + + $object_phid = $xaction->getObjectPHID(); + $author_phid = $xaction->getAuthorPHID(); + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + + if ($old) { + return pht( + '%s updated the repository for %s from %s to %s.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($object_phid), + $xaction->renderHandleLink($old), + $xaction->renderHandleLink($new)); + } else { + return pht( + '%s set the repository for %s to %s.', + $xaction->renderHandleLink($author_phid), + $xaction->renderHandleLink($object_phid), + $xaction->renderHandleLink($new)); + } + } + +} diff --git a/src/applications/differential/customfield/DifferentialSummaryField.php b/src/applications/differential/customfield/DifferentialSummaryField.php index 60aa173841..9db2651f6f 100644 --- a/src/applications/differential/customfield/DifferentialSummaryField.php +++ b/src/applications/differential/customfield/DifferentialSummaryField.php @@ -30,7 +30,7 @@ final class DifferentialSummaryField $this->setValue($request->getStr($this->getFieldKey())); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new PhabricatorRemarkupControl()) ->setName($this->getFieldKey()) ->setValue($this->getValue()) diff --git a/src/applications/differential/customfield/DifferentialTestPlanField.php b/src/applications/differential/customfield/DifferentialTestPlanField.php index 2ddd8ffa86..ba22675c7c 100644 --- a/src/applications/differential/customfield/DifferentialTestPlanField.php +++ b/src/applications/differential/customfield/DifferentialTestPlanField.php @@ -44,7 +44,7 @@ final class DifferentialTestPlanField $this->setValue($request->getStr($this->getFieldKey())); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new PhabricatorRemarkupControl()) ->setName($this->getFieldKey()) ->setValue($this->getValue()) diff --git a/src/applications/differential/customfield/DifferentialTitleField.php b/src/applications/differential/customfield/DifferentialTitleField.php index b0f9217727..0eb80df825 100644 --- a/src/applications/differential/customfield/DifferentialTitleField.php +++ b/src/applications/differential/customfield/DifferentialTitleField.php @@ -38,7 +38,7 @@ final class DifferentialTitleField return true; } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextAreaControl()) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) ->setName($this->getFieldKey()) diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index 48fd3cdc12..bdfa201017 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -468,6 +468,8 @@ final class DifferentialRevision extends DifferentialDAO $fields = array( new DifferentialTitleField(), new DifferentialSummaryField(), + new DifferentialTestPlanField(), + new DifferentialRepositoryField(), ); return array_fill_keys( diff --git a/src/applications/maniphest/controller/ManiphestTaskEditController.php b/src/applications/maniphest/controller/ManiphestTaskEditController.php index 393a713b60..ecdbae0829 100644 --- a/src/applications/maniphest/controller/ManiphestTaskEditController.php +++ b/src/applications/maniphest/controller/ManiphestTaskEditController.php @@ -157,10 +157,10 @@ final class ManiphestTaskEditController extends ManiphestController { $field_list = PhabricatorCustomField::getObjectFields( $task, PhabricatorCustomField::ROLE_EDIT); + $field_list->setViewer($user); foreach ($field_list->getFields() as $field) { $field->setObject($task); - $field->setViewer($user); } $field_list->readFieldsFromStorage($task); @@ -577,10 +577,7 @@ final class ManiphestTaskEditController extends ManiphestController { ->setDatasource('/typeahead/common/projects/')); } - foreach ($aux_fields as $aux_field) { - $aux_control = $aux_field->renderEditControl(); - $form->appendChild($aux_control); - } + $field_list->appendFieldsToForm($form); require_celerity_resource('aphront-error-view-css'); diff --git a/src/applications/people/customfield/PhabricatorUserBlurbField.php b/src/applications/people/customfield/PhabricatorUserBlurbField.php index 851a654d97..5e9c5627f8 100644 --- a/src/applications/people/customfield/PhabricatorUserBlurbField.php +++ b/src/applications/people/customfield/PhabricatorUserBlurbField.php @@ -50,7 +50,7 @@ final class PhabricatorUserBlurbField $this->value = $request->getStr($this->getFieldKey()); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new PhabricatorRemarkupControl()) ->setName($this->getFieldKey()) ->setValue($this->value) diff --git a/src/applications/people/customfield/PhabricatorUserRealNameField.php b/src/applications/people/customfield/PhabricatorUserRealNameField.php index bf18b98563..87a062d211 100644 --- a/src/applications/people/customfield/PhabricatorUserRealNameField.php +++ b/src/applications/people/customfield/PhabricatorUserRealNameField.php @@ -53,7 +53,7 @@ final class PhabricatorUserRealNameField $this->value = $request->getStr($this->getFieldKey()); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setName($this->getFieldKey()) ->setValue($this->value) diff --git a/src/applications/people/customfield/PhabricatorUserTitleField.php b/src/applications/people/customfield/PhabricatorUserTitleField.php index 39ad979320..472abe1639 100644 --- a/src/applications/people/customfield/PhabricatorUserTitleField.php +++ b/src/applications/people/customfield/PhabricatorUserTitleField.php @@ -50,7 +50,7 @@ final class PhabricatorUserTitleField $this->value = $request->getStr($this->getFieldKey()); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setName($this->getFieldKey()) ->setValue($this->value) diff --git a/src/applications/releeph/field/specification/ReleephLevelFieldSpecification.php b/src/applications/releeph/field/specification/ReleephLevelFieldSpecification.php index e67a01877d..4d09cac45a 100644 --- a/src/applications/releeph/field/specification/ReleephLevelFieldSpecification.php +++ b/src/applications/releeph/field/specification/ReleephLevelFieldSpecification.php @@ -27,7 +27,7 @@ abstract class ReleephLevelFieldSpecification return $this->getNameForLevel($this->getValue()); } - public function renderEditControl() { + public function renderEditControl(array $handles) { $control_name = $this->getRequiredStorageKey(); $all_levels = $this->getLevels(); diff --git a/src/applications/releeph/field/specification/ReleephReasonFieldSpecification.php b/src/applications/releeph/field/specification/ReleephReasonFieldSpecification.php index 885c096b89..73ae4ebbba 100644 --- a/src/applications/releeph/field/specification/ReleephReasonFieldSpecification.php +++ b/src/applications/releeph/field/specification/ReleephReasonFieldSpecification.php @@ -35,7 +35,7 @@ final class ReleephReasonFieldSpecification private $error = true; - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextAreaControl()) ->setLabel('Reason') ->setName('reason') diff --git a/src/applications/releeph/field/specification/ReleephSummaryFieldSpecification.php b/src/applications/releeph/field/specification/ReleephSummaryFieldSpecification.php index e1f67db6cf..6be5bc714b 100644 --- a/src/applications/releeph/field/specification/ReleephSummaryFieldSpecification.php +++ b/src/applications/releeph/field/specification/ReleephSummaryFieldSpecification.php @@ -19,7 +19,7 @@ final class ReleephSummaryFieldSpecification private $error = false; - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setLabel('Summary') ->setName('summary') diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php index 2e0b724302..5609148be2 100644 --- a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php +++ b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php @@ -96,27 +96,6 @@ abstract class PhabricatorApplicationTransactionQuery } } - if ($this->needHandles) { - $phids = array(); - foreach ($xactions as $xaction) { - $phids[$xaction->getPHID()] = $xaction->getRequiredHandlePHIDs(); - } - $handles = array(); - $merged = array_mergev($phids); - if ($merged) { - $handles = id(new PhabricatorHandleQuery()) - ->setViewer($this->getViewer()) - ->withPHIDs($merged) - ->execute(); - } - foreach ($xactions as $xaction) { - $xaction->setHandles( - array_select_keys( - $handles, - $phids[$xaction->getPHID()])); - } - } - return $xactions; } @@ -138,6 +117,31 @@ abstract class PhabricatorApplicationTransactionQuery $xaction->attachObject($objects[$object_phid]); } + // NOTE: We have to do this after loading objects, because the objects + // may help determine which handles are required (for example, in the case + // of custom fields. + + if ($this->needHandles) { + $phids = array(); + foreach ($xactions as $xaction) { + $phids[$xaction->getPHID()] = $xaction->getRequiredHandlePHIDs(); + } + $handles = array(); + $merged = array_mergev($phids); + if ($merged) { + $handles = id(new PhabricatorHandleQuery()) + ->setViewer($this->getViewer()) + ->withPHIDs($merged) + ->execute(); + } + foreach ($xactions as $xaction) { + $xaction->setHandles( + array_select_keys( + $handles, + $phids[$xaction->getPHID()])); + } + } + return $xactions; } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 2b4b282d76..dc58105878 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -148,6 +148,13 @@ abstract class PhabricatorApplicationTransaction $phids[] = array($this->getAuthorPHID()); switch ($this->getTransactionType()) { + case PhabricatorTransactions::TYPE_CUSTOMFIELD: + $field = $this->getTransactionCustomField(); + if ($field) { + $phids[] = $field->getApplicationTransactionRequiredHandlePHIDs( + $this); + } + break; case PhabricatorTransactions::TYPE_SUBSCRIBERS: $phids[] = $old; $phids[] = $new; diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index f8e9e69454..6b07434480 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -924,6 +924,15 @@ abstract class PhabricatorCustomField { return null; } + public function getApplicationTransactionRequiredHandlePHIDs( + PhabricatorApplicationTransaction $xaction) { + if ($this->proxy) { + return $this->proxy->getApplicationTransactionRequiredHandlePHIDs( + $xaction); + } + return array(); + } + /* -( Edit View )---------------------------------------------------------- */ @@ -953,9 +962,20 @@ abstract class PhabricatorCustomField { /** * @task edit */ - public function renderEditControl() { + public function getRequiredHandlePHIDsForEdit() { if ($this->proxy) { - return $this->proxy->renderEditControl(); + return $this->proxy->getRequiredHandlePHIDsForEdit(); + } + return array(); + } + + + /** + * @task edit + */ + public function renderEditControl(array $handles) { + if ($this->proxy) { + return $this->proxy->renderEditControl($handles); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } diff --git a/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php b/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php index 24647f07d9..c590365f40 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomFieldList.php @@ -10,6 +10,7 @@ final class PhabricatorCustomFieldList extends Phobject { private $fields; + private $viewer; public function __construct(array $fields) { assert_instances_of($fields, 'PhabricatorCustomField'); @@ -21,6 +22,7 @@ final class PhabricatorCustomFieldList extends Phobject { } public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; foreach ($this->getFields() as $field) { $field->setViewer($viewer); } @@ -75,11 +77,32 @@ final class PhabricatorCustomFieldList extends Phobject { } public function appendFieldsToForm(AphrontFormView $form) { + $enabled = array(); foreach ($this->fields as $field) { if ($field->shouldEnableForRole(PhabricatorCustomField::ROLE_EDIT)) { - $form->appendChild($field->renderEditControl()); + $enabled[] = $field; } } + + $phids = array(); + foreach ($enabled as $field_key => $field) { + $phids[$field_key] = $field->getRequiredHandlePHIDsForEdit(); + } + + $all_phids = array_mergev($phids); + if ($all_phids) { + $handles = id(new PhabricatorHandleQuery()) + ->setViewer($this->viewer) + ->withPHIDs($all_phids) + ->execute(); + } else { + $handles = array(); + } + + foreach ($enabled as $field_key => $field) { + $field_handles = array_select_keys($handles, $phids[$field_key]); + $form->appendChild($field->renderEditControl($field_handles)); + } } public function appendFieldsToPropertyList( diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index 947a7ca7ae..702632aa75 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -200,7 +200,7 @@ abstract class PhabricatorStandardCustomField $this->setFieldValue($value); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setName($this->getFieldKey()) ->setCaption($this->getCaption()) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php index da797f8e4c..b52d6570a3 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php @@ -72,7 +72,7 @@ final class PhabricatorStandardCustomFieldBool ))); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormCheckboxControl()) ->setLabel($this->getFieldName()) ->setCaption($this->getCaption()) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php index 943f6c1e91..5754885cf7 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php @@ -36,7 +36,7 @@ final class PhabricatorStandardCustomFieldDate return $this->setFieldValue($value); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return $this->newDateControl(); } diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php index a56ad13290..256f23b75a 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php @@ -7,7 +7,7 @@ final class PhabricatorStandardCustomFieldHeader return 'header'; } - public function renderEditControl() { + public function renderEditControl(array $handles) { $header = phutil_tag( 'div', array( diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php index 755f4fcdc1..c3b46a2e83 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php @@ -86,4 +86,75 @@ abstract class PhabricatorStandardCustomFieldPHIDs return $handles; } + public function getRequiredHandlePHIDsForEdit() { + $value = $this->getFieldValue(); + if ($value) { + return $value; + } else { + return array(); + } + } + + public function getApplicationTransactionRequiredHandlePHIDs( + PhabricatorApplicationTransaction $xaction) { + + $old = json_decode($xaction->getOldValue()); + if (!is_array($old)) { + $old = array(); + } + + $new = json_decode($xaction->getNewValue()); + if (!is_array($new)) { + $new = array(); + } + + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + + return array_merge($add, $rem); + } + + public function getApplicationTransactionTitle( + PhabricatorApplicationTransaction $xaction) { + $author_phid = $xaction->getAuthorPHID(); + + $old = json_decode($xaction->getOldValue()); + if (!is_array($old)) { + $old = array(); + } + + $new = json_decode($xaction->getNewValue()); + if (!is_array($new)) { + $new = array(); + } + + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + + if ($add && !$rem) { + return pht( + '%s updated %s, added %d: %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + new PhutilNumber(count($add)), + $xaction->renderHandleList($add)); + } else if ($rem && !$add) { + return pht( + '%s updated %s, removed %d: %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + new PhutilNumber(count($rem)), + $xaction->renderHandleList($rem)); + } else { + return pht( + '%s updated %s, added %d: %s; removed %d: %s.', + $xaction->renderHandleLink($author_phid), + $this->getFieldName(), + new PhutilNumber(count($add)), + $xaction->renderHandleList($add), + new PhutilNumber(count($rem)), + $xaction->renderHandleList($rem)); + } + } + } diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php index b05ef94c24..ee79aab76b 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php @@ -7,7 +7,7 @@ final class PhabricatorStandardCustomFieldRemarkup return 'remarkup'; } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new PhabricatorRemarkupControl()) ->setLabel($this->getFieldName()) ->setName($this->getFieldKey()) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php index c0cce662a5..969ab58968 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php @@ -64,7 +64,7 @@ final class PhabricatorStandardCustomFieldSelect return $this->getFieldConfigValue('options', array()); } - public function renderEditControl() { + public function renderEditControl(array $handles) { return id(new AphrontFormSelectControl()) ->setLabel($this->getFieldName()) ->setCaption($this->getCaption()) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php index c60641383c..4534191766 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php @@ -7,17 +7,12 @@ final class PhabricatorStandardCustomFieldUsers return 'users'; } - public function renderEditControl() { - $handles = array(); + public function renderEditControl(array $handles) { $value = $this->getFieldValue(); if ($value) { - - // TODO: Surface and batch. - - $handles = id(new PhabricatorHandleQuery()) - ->setViewer($this->getViewer()) - ->withPHIDs($value) - ->execute(); + $control_value = array_select_keys($handles, $value); + } else { + $control_value = array(); } $control = id(new AphrontFormTokenizerControl()) @@ -25,7 +20,7 @@ final class PhabricatorStandardCustomFieldUsers ->setName($this->getFieldKey()) ->setDatasource('/typeahead/common/accounts/') ->setCaption($this->getCaption()) - ->setValue($handles); + ->setValue($control_value); $limit = $this->getFieldConfigValue('limit'); if ($limit) { @@ -49,18 +44,4 @@ final class PhabricatorStandardCustomFieldUsers $form->appendChild($control); } - - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - - // TODO: Show added/removed and render handles. We don't have handle - // surfacing or batching yet so this is a bit awkward right now. - - return pht( - '%s updated %s.', - $xaction->renderHandleLink($author_phid), - $this->getFieldName()); - } }