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 @@ -2514,6 +2514,7 @@ 'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php', 'PhabricatorDisplayPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDisplayPreferencesSettingsPanel.php', 'PhabricatorDisqusAuthProvider' => 'applications/auth/provider/PhabricatorDisqusAuthProvider.php', + 'PhabricatorDividerEditField' => 'applications/transactions/editfield/PhabricatorDividerEditField.php', 'PhabricatorDividerProfileMenuItem' => 'applications/search/menuitem/PhabricatorDividerProfileMenuItem.php', 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', @@ -3825,6 +3826,7 @@ 'PhabricatorStreamingProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorStreamingProtocolAdapter.php', 'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php', 'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php', + 'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorSubscribedToObjectEdgeType.php', 'PhabricatorSubscribersEditField' => 'applications/transactions/editfield/PhabricatorSubscribersEditField.php', @@ -7468,6 +7470,7 @@ 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisplayPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDisqusAuthProvider' => 'PhabricatorOAuth2AuthProvider', + 'PhabricatorDividerEditField' => 'PhabricatorEditField', 'PhabricatorDividerProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', @@ -9024,6 +9027,7 @@ 'PhabricatorStreamingProtocolAdapter' => 'PhabricatorProtocolAdapter', 'PhabricatorStringListEditField' => 'PhabricatorEditField', 'PhabricatorStringSetting' => 'PhabricatorSetting', + 'PhabricatorSubmitEditField' => 'PhabricatorEditField', 'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorSubscribersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -69,6 +69,8 @@ => 'DifferentialRevisionEditController', $this->getEditRoutePattern('editpro/') => 'DifferentialRevisionEditProController', + $this->getEditRoutePattern('attach/(?P[^/]+)/to/') + => 'DifferentialRevisionEditProController', 'land/(?:(?P[1-9]\d*))/(?P[^/]+)/' => 'DifferentialRevisionLandController', 'closedetails/(?P[^/]+)/' diff --git a/src/applications/differential/controller/DifferentialRevisionEditProController.php b/src/applications/differential/controller/DifferentialRevisionEditProController.php --- a/src/applications/differential/controller/DifferentialRevisionEditProController.php +++ b/src/applications/differential/controller/DifferentialRevisionEditProController.php @@ -4,9 +4,53 @@ extends DifferentialController { public function handleRequest(AphrontRequest $request) { - return id(new DifferentialRevisionEditEngine()) - ->setController($this) - ->buildResponse(); + $viewer = $this->getViewer(); + + // If we have a Diff ID, this is an "/attach/123/to/456/" action. The + // user just created a diff and is trying to use it to create or update + // a revision. + $diff_id = $request->getURIData('diffID'); + + if ($diff_id) { + $diff = id(new DifferentialDiffQuery()) + ->setViewer($viewer) + ->withIDs(array($diff_id)) + ->executeOne(); + if (!$diff) { + return new Aphront404Response(); + } + + if ($diff->getRevisionID()) { + $revision = $diff->getRevision(); + return $this->newDialog() + ->setTitle(pht('Diff Already Attached')) + ->appendParagraph( + pht( + 'This diff is already attached to a revision.')) + ->addCancelButton($revision->getURI(), pht('Continue')); + } + } else { + $diff = null; + } + + $revision_id = $request->getURIData('id'); + if (!$diff && !$revision_id) { + return $this->newDialog() + ->setTitle(pht('Diff Required')) + ->appendParagraph( + pht( + 'You can not create a revision without a diff.')) + ->addCancelButton($this->getApplicationURI()); + } + + $engine = id(new DifferentialRevisionEditEngine()) + ->setController($this); + + if ($diff) { + $engine->setDiff($diff); + } + + return $engine->buildResponse(); } } diff --git a/src/applications/differential/editor/DifferentialRevisionEditEngine.php b/src/applications/differential/editor/DifferentialRevisionEditEngine.php --- a/src/applications/differential/editor/DifferentialRevisionEditEngine.php +++ b/src/applications/differential/editor/DifferentialRevisionEditEngine.php @@ -3,6 +3,8 @@ final class DifferentialRevisionEditEngine extends PhabricatorEditEngine { + private $diff; + const ENGINECONST = 'differential.revision'; public function getEngineName() { @@ -33,6 +35,7 @@ protected function newObjectQuery() { return id(new DifferentialRevisionQuery()) + ->needActiveDiffs(true) ->needReviewerStatus(true); } @@ -41,7 +44,15 @@ } protected function getObjectEditTitleText($object) { - return pht('Edit Revision: %s', $object->getTitle()); + $monogram = $object->getMonogram(); + $title = $object->getTitle(); + + $diff = $this->getDiff(); + if ($diff) { + return pht('Update Revision %s: %s', $monogram, $title); + } else { + return pht('Edit Revision %s: %s', $monogram, $title); + } } protected function getObjectEditShortText($object) { @@ -60,6 +71,15 @@ return $object->getURI(); } + public function setDiff(DifferentialDiff $diff) { + $this->diff = $diff; + return $this; + } + + public function getDiff() { + return $this->diff; + } + protected function buildCustomEditFields($object) { $plan_required = PhabricatorEnv::getEnvConfig( @@ -68,7 +88,48 @@ $object, 'differential:test-plan'); + $diff = $this->getDiff(); + if ($diff) { + $diff_phid = $diff->getPHID(); + } else { + $diff_phid = null; + } + + $is_update = ($diff && $object->getID()); + $fields = array(); + + $fields[] = id(new PhabricatorHandlesEditField()) + ->setKey('update') + ->setLabel(pht('Update Diff')) + ->setDescription(pht('New diff to create or update the revision with.')) + ->setConduitDescription(pht('Create or update a revision with a diff.')) + ->setConduitTypeDescription(pht('PHID of the diff.')) + ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) + ->setHandleParameterType(new AphrontPHIDListHTTPParameterType()) + ->setSingleValue($diff_phid) + ->setIsReorderable(false) + ->setIsDefaultable(false) + ->setIsInvisible(true) + ->setIsLockable(false); + + if ($is_update) { + $fields[] = id(new PhabricatorInstructionsEditField()) + ->setKey('update.help') + ->setValue(pht('Describe the updates you have made to the diff.')); + $fields[] = id(new PhabricatorCommentEditField()) + ->setKey('update.comment') + ->setLabel(pht('Comment')) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->setIsWebOnly(true) + ->setDescription(pht('Comments providing context for the update.')); + $fields[] = id(new PhabricatorSubmitEditField()) + ->setKey('update.submit') + ->setValue($this->getObjectEditButtonText($object)); + $fields[] = id(new PhabricatorDividerEditField()) + ->setKey('update.note'); + } + $fields[] = id(new PhabricatorTextEditField()) ->setKey('title') ->setLabel(pht('Title')) diff --git a/src/applications/transactions/editfield/PhabricatorCommentEditField.php b/src/applications/transactions/editfield/PhabricatorCommentEditField.php --- a/src/applications/transactions/editfield/PhabricatorCommentEditField.php +++ b/src/applications/transactions/editfield/PhabricatorCommentEditField.php @@ -3,6 +3,17 @@ final class PhabricatorCommentEditField extends PhabricatorEditField { + private $isWebOnly; + + public function setIsWebOnly($is_web_only) { + $this->isWebOnly = $is_web_only; + return $this; + } + + public function getIsWebOnly() { + return $this->isWebOnly; + } + protected function newControl() { return new PhabricatorRemarkupControl(); } @@ -12,15 +23,23 @@ } protected function newConduitParameterType() { - return new ConduitStringParameterType(); + if ($this->getIsWebOnly()) { + return null; + } else { + return new ConduitStringParameterType(); + } } public function shouldGenerateTransactionsFromSubmit() { - return false; + return !$this->isPrimaryCommentField(); } public function shouldGenerateTransactionsFromComment() { - return true; + return $this->isPrimaryCommentField(); + } + + private function isPrimaryCommentField() { + return ($this->getKey() === 'comment'); } } diff --git a/src/applications/transactions/editfield/PhabricatorDividerEditField.php b/src/applications/transactions/editfield/PhabricatorDividerEditField.php new file mode 100644 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorDividerEditField.php @@ -0,0 +1,18 @@ +setValue($this->getValue()); + } + + protected function newHTTPParameterType() { + return null; + } + + protected function newConduitParameterType() { + return null; + } + +}