diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3941,6 +3941,7 @@ 'PhabricatorSubscriptionsTransactionController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php', 'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php', 'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php', + 'PhabricatorSubtypeEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php', 'PhabricatorSupportApplication' => 'applications/support/application/PhabricatorSupportApplication.php', 'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php', 'PhabricatorSyntaxHighlightingConfigOptions' => 'applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php', @@ -9241,6 +9242,7 @@ 'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController', 'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener', 'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', + 'PhabricatorSubtypeEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorSupportApplication' => 'PhabricatorApplication', 'PhabricatorSyntaxHighlighter' => 'Phobject', 'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions', diff --git a/src/applications/maniphest/storage/ManiphestTransaction.php b/src/applications/maniphest/storage/ManiphestTransaction.php --- a/src/applications/maniphest/storage/ManiphestTransaction.php +++ b/src/applications/maniphest/storage/ManiphestTransaction.php @@ -404,7 +404,12 @@ return pht( '%s created this task.', $this->renderHandleLink($author_phid)); - + case PhabricatorTransactions::TYPE_SUBTYPE: + return pht( + '%s changed the subtype of this task from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->renderSubtypeName($old), + $this->renderSubtypeName($new)); case self::TYPE_TITLE: if ($old === null) { return pht( @@ -876,11 +881,28 @@ $this->renderHandleList($new), $this->renderHandleLink($object_phid)); + case PhabricatorTransactions::TYPE_SUBTYPE: + return pht( + '%s changed the subtype of %s from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $this->renderSubtypeName($old), + $this->renderSubtypeName($new)); } return parent::getTitleForFeed(); } + private function renderSubtypeName($value) { + $object = $this->getObject(); + $map = $object->newEditEngineSubtypeMap(); + if (!isset($map[$value])) { + return $value; + } + + return $map[$value]->getName(); + } + public function hasChangeDetails() { switch ($this->getTransactionType()) { case self::TYPE_DESCRIPTION: diff --git a/src/applications/transactions/constants/PhabricatorTransactions.php b/src/applications/transactions/constants/PhabricatorTransactions.php --- a/src/applications/transactions/constants/PhabricatorTransactions.php +++ b/src/applications/transactions/constants/PhabricatorTransactions.php @@ -15,6 +15,7 @@ const TYPE_SPACE = 'core:space'; const TYPE_CREATE = 'core:create'; const TYPE_COLUMNS = 'core:columns'; + const TYPE_SUBTYPE = 'core:subtype'; const COLOR_RED = 'red'; const COLOR_ORANGE = 'orange'; diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php --- a/src/applications/transactions/editengine/PhabricatorEditEngine.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php @@ -976,6 +976,9 @@ $fields = $this->buildEditFields($object); $template = $object->getApplicationTransactionTemplate(); + $config = $this->getEditEngineConfiguration() + ->attachEngine($this); + $validation_exception = null; if ($request->isFormPost() && $request->getBool('editEngine')) { $submit_fields = $fields; @@ -1010,6 +1013,12 @@ if ($this->getIsCreate()) { $xactions[] = id(clone $template) ->setTransactionType(PhabricatorTransactions::TYPE_CREATE); + + if ($this->supportsSubtypes()) { + $xactions[] = id(clone $template) + ->setTransactionType(PhabricatorTransactions::TYPE_SUBTYPE) + ->setNewValue($config->getSubtype()); + } } foreach ($submit_fields as $key => $field) { diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php --- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php +++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php @@ -261,6 +261,10 @@ $types[] = PhabricatorTransactions::TYPE_CREATE; + if ($this->object instanceof PhabricatorEditEngineSubtypeInterface) { + $types[] = PhabricatorTransactions::TYPE_SUBTYPE; + } + if ($this->object instanceof PhabricatorSubscribableInterface) { $types[] = PhabricatorTransactions::TYPE_SUBSCRIBERS; } @@ -324,6 +328,8 @@ switch ($type) { case PhabricatorTransactions::TYPE_CREATE: return null; + case PhabricatorTransactions::TYPE_SUBTYPE: + return $object->getEditEngineSubtype(); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return array_values($this->subscribers); case PhabricatorTransactions::TYPE_VIEW_POLICY: @@ -410,6 +416,7 @@ case PhabricatorTransactions::TYPE_BUILDABLE: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_INLINESTATE: + case PhabricatorTransactions::TYPE_SUBTYPE: return $xaction->getNewValue(); case PhabricatorTransactions::TYPE_SPACE: $space_phid = $xaction->getNewValue(); @@ -542,6 +549,7 @@ $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->applyApplicationTransactionInternalEffects($xaction); case PhabricatorTransactions::TYPE_CREATE: + case PhabricatorTransactions::TYPE_SUBTYPE: case PhabricatorTransactions::TYPE_BUILDABLE: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_VIEW_POLICY: @@ -601,6 +609,7 @@ $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->applyApplicationTransactionExternalEffects($xaction); case PhabricatorTransactions::TYPE_CREATE: + case PhabricatorTransactions::TYPE_SUBTYPE: case PhabricatorTransactions::TYPE_EDGE: case PhabricatorTransactions::TYPE_BUILDABLE: case PhabricatorTransactions::TYPE_TOKEN: @@ -664,6 +673,9 @@ case PhabricatorTransactions::TYPE_SPACE: $object->setSpacePHID($xaction->getNewValue()); break; + case PhabricatorTransactions::TYPE_SUBTYPE: + $object->setEditEngineSubtype($xaction->getNewValue()); + break; } } @@ -2103,6 +2115,12 @@ $xactions, $type); break; + case PhabricatorTransactions::TYPE_SUBTYPE: + $errors[] = $this->validateSubtypeTransactions( + $object, + $xactions, + $type); + break; case PhabricatorTransactions::TYPE_CUSTOMFIELD: $groups = array(); foreach ($xactions as $xaction) { @@ -2254,6 +2272,35 @@ return $errors; } + private function validateSubtypeTransactions( + PhabricatorLiskDAO $object, + array $xactions, + $transaction_type) { + $errors = array(); + + $map = $object->newEditEngineSubtypeMap(); + $old = $object->getEditEngineSubtype(); + foreach ($xactions as $xaction) { + $new = $xaction->getNewValue(); + + if ($old == $new) { + continue; + } + + if (!isset($map[$new])) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + $transaction_type, + pht('Invalid'), + pht( + 'The subtype "%s" is not a valid subtype.', + $new), + $xaction); + continue; + } + } + + return $errors; + } protected function adjustObjectForPolicyChecks( PhabricatorLiskDAO $object, diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php --- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php +++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php @@ -57,7 +57,9 @@ } break; case PhabricatorEditEngineConfigurationTransaction::TYPE_SUBTYPE: - $map = $object->getEngine()->newSubtypeMap(); + $map = $object->getEngine() + ->setViewer($this->getActor()) + ->newSubtypeMap(); foreach ($xactions as $xaction) { $new = $xaction->getNewValue(); diff --git a/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php b/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php new file mode 100644 --- /dev/null +++ b/src/applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.php @@ -0,0 +1,51 @@ +supportsSubtypes(); + } + + public function buildCustomEditFields( + PhabricatorEditEngine $engine, + PhabricatorApplicationTransactionInterface $object) { + + $subtype_type = PhabricatorTransactions::TYPE_SUBTYPE; + + $subtype_field = id(new PhabricatorSelectEditField()) + ->setKey(self::EDITKEY) + ->setLabel(pht('Subtype')) + ->setIsConduitOnly(true) + ->setIsHidden(true) + ->setIsReorderable(false) + ->setIsDefaultable(false) + ->setIsLockable(false) + ->setTransactionType($subtype_type) + ->setConduitDescription(pht('Change the object subtype.')) + ->setConduitTypeDescription(pht('New object subtype key.')) + ->setValue($object->getEditEngineSubtype()); + + return array( + $subtype_field, + ); + } + +} diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -546,6 +546,8 @@ case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_SPACE: break; + case PhabricatorTransactions::TYPE_SUBTYPE: + return true; default: $old = $this->getOldValue();