From f3f1f9dc577ac9675accae0f5870e55a08a3f258 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 26 Dec 2017 10:17:27 -0800 Subject: [PATCH] Allow "drydock.blueprint.edit" to create blueprints Summary: Depends on D18848. Ref PHI243. This puts a bit of logic up front to figure out the blueprint type before we actually start editing it. This implementation is a little messy but it keeps the API clean. Eventually, the implementation could probably go in the TransactionTypes so more code is shared, but I'd like to wait for a couple more of these first. This capability probably isn't too useful, but just pays down a bit of technical debt from the caveat introduced in D18822. Test Plan: - Created a new blueprint with the API. - Tried to create a blueprint without a "type" (got a helpful error). - Created and edited blueprints via the web UI. - Tried to change the "type" of an existing blueprint (got a helpful error). Reviewers: amckinley Reviewed By: amckinley Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam Differential Revision: https://secure.phabricator.com/D18849 --- src/__phutil_library_map__.php | 2 + .../DrydockBlueprintEditConduitAPIMethod.php | 3 +- .../editor/DrydockBlueprintEditEngine.php | 45 ++++++++++++++- .../DrydockBlueprintTypeTransaction.php | 57 +++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/applications/drydock/xaction/DrydockBlueprintTypeTransaction.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 0a005eef4a..f4a410ad2e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1025,6 +1025,7 @@ phutil_register_library_map(array( 'DrydockBlueprintTransaction' => 'applications/drydock/storage/DrydockBlueprintTransaction.php', 'DrydockBlueprintTransactionQuery' => 'applications/drydock/query/DrydockBlueprintTransactionQuery.php', 'DrydockBlueprintTransactionType' => 'applications/drydock/xaction/DrydockBlueprintTransactionType.php', + 'DrydockBlueprintTypeTransaction' => 'applications/drydock/xaction/DrydockBlueprintTypeTransaction.php', 'DrydockBlueprintViewController' => 'applications/drydock/controller/DrydockBlueprintViewController.php', 'DrydockCommand' => 'applications/drydock/storage/DrydockCommand.php', 'DrydockCommandError' => 'applications/drydock/exception/DrydockCommandError.php', @@ -6122,6 +6123,7 @@ phutil_register_library_map(array( 'DrydockBlueprintTransaction' => 'PhabricatorModularTransaction', 'DrydockBlueprintTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DrydockBlueprintTransactionType' => 'PhabricatorModularTransactionType', + 'DrydockBlueprintTypeTransaction' => 'DrydockBlueprintTransactionType', 'DrydockBlueprintViewController' => 'DrydockBlueprintController', 'DrydockCommand' => array( 'DrydockDAO', diff --git a/src/applications/drydock/conduit/DrydockBlueprintEditConduitAPIMethod.php b/src/applications/drydock/conduit/DrydockBlueprintEditConduitAPIMethod.php index 764c077d87..7a120f7c5b 100644 --- a/src/applications/drydock/conduit/DrydockBlueprintEditConduitAPIMethod.php +++ b/src/applications/drydock/conduit/DrydockBlueprintEditConduitAPIMethod.php @@ -13,8 +13,7 @@ final class DrydockBlueprintEditConduitAPIMethod public function getMethodSummary() { return pht( - 'WARNING: Apply transactions to edit an existing blueprint. This method '. - 'can not create new blueprints.'); + 'Apply transactions to create or edit a blueprint.'); } } diff --git a/src/applications/drydock/editor/DrydockBlueprintEditEngine.php b/src/applications/drydock/editor/DrydockBlueprintEditEngine.php index bd91aa3350..6bd1366ef0 100644 --- a/src/applications/drydock/editor/DrydockBlueprintEditEngine.php +++ b/src/applications/drydock/editor/DrydockBlueprintEditEngine.php @@ -51,6 +51,38 @@ final class DrydockBlueprintEditEngine return $blueprint; } + protected function newEditableObjectFromConduit(array $raw_xactions) { + $type = null; + foreach ($raw_xactions as $raw_xaction) { + if ($raw_xaction['type'] !== 'type') { + continue; + } + + $type = $raw_xaction['value']; + } + + if ($type === null) { + throw new Exception( + pht( + 'When creating a new Drydock blueprint via the Conduit API, you '. + 'must provide a "type" transaction to select a type.')); + } + + $map = DrydockBlueprintImplementation::getAllBlueprintImplementations(); + if (!isset($map[$type])) { + throw new Exception( + pht( + 'Blueprint type "%s" is unrecognized. Valid types are: %s.', + $type, + implode(', ', array_keys($map)))); + } + + $impl = clone $map[$type]; + $this->setBlueprintImplementation($impl); + + return $this->newEditableObject(); + } + protected function newEditableObjectForDocumentation() { // In order to generate the proper list of fields/transactions for a // blueprint, a blueprint's type needs to be known upfront, and there's @@ -112,11 +144,22 @@ final class DrydockBlueprintEditEngine $impl = $object->getImplementation(); return array( + // This field appears in the web UI id(new PhabricatorStaticEditField()) - ->setKey('type') + ->setKey('displayType') ->setLabel(pht('Blueprint Type')) ->setDescription(pht('Type of blueprint.')) ->setValue($impl->getBlueprintName()), + id(new PhabricatorTextEditField()) + ->setKey('type') + ->setLabel(pht('Type')) + ->setIsConduitOnly(true) + ->setTransactionType( + DrydockBlueprintTypeTransaction::TRANSACTIONTYPE) + ->setDescription(pht('When creating a blueprint, set the type.')) + ->setConduitDescription(pht('Set the blueprint type.')) + ->setConduitTypeDescription(pht('Blueprint type.')) + ->setValue($object->getClassName()), id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) diff --git a/src/applications/drydock/xaction/DrydockBlueprintTypeTransaction.php b/src/applications/drydock/xaction/DrydockBlueprintTypeTransaction.php new file mode 100644 index 0000000000..024e6092fa --- /dev/null +++ b/src/applications/drydock/xaction/DrydockBlueprintTypeTransaction.php @@ -0,0 +1,57 @@ +getClassName(); + } + + public function applyInternalEffects($object, $value) { + $object->setClassName($value); + } + + public function getTitle() { + // These transactions can only be applied during object creation and never + // generate a timeline event. + return null; + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $name = $object->getClassName(); + if ($this->isEmptyTextTransaction($name, $xactions)) { + $errors[] = $this->newRequiredError( + pht('You must select a blueprint type when creating a blueprint.')); + } + + $map = DrydockBlueprintImplementation::getAllBlueprintImplementations(); + + foreach ($xactions as $xaction) { + if (!$this->isNewObject()) { + $errors[] = $this->newInvalidError( + pht( + 'The type of a blueprint can not be changed once it has '. + 'been created.'), + $xaction); + continue; + } + + $new = $xaction->getNewValue(); + if (!isset($map[$new])) { + $errors[] = $this->newInvalidError( + pht( + 'Blueprint type "%s" is not valid. Valid types are: %s.', + $new, + implode(', ', array_keys($map)))); + continue; + } + } + + return $errors; + } + +}