Path: blob/master/src/applications/differential/editor/DifferentialRevisionEditEngine.php
12256 views
<?php12final class DifferentialRevisionEditEngine3extends PhabricatorEditEngine {45private $diff;67const ENGINECONST = 'differential.revision';89const ACTIONGROUP_REVIEW = 'review';10const ACTIONGROUP_REVISION = 'revision';1112public function getEngineName() {13return pht('Revisions');14}1516public function getSummaryHeader() {17return pht('Configure Revision Forms');18}1920public function getSummaryText() {21return pht(22'Configure creation and editing revision forms in Differential.');23}2425public function getEngineApplicationClass() {26return 'PhabricatorDifferentialApplication';27}2829public function isEngineConfigurable() {30return false;31}3233protected function newEditableObject() {34$viewer = $this->getViewer();35return DifferentialRevision::initializeNewRevision($viewer);36}3738protected function newObjectQuery() {39return id(new DifferentialRevisionQuery())40->needActiveDiffs(true)41->needReviewers(true)42->needReviewerAuthority(true);43}4445protected function getObjectCreateTitleText($object) {46return pht('Create New Revision');47}4849protected function getObjectEditTitleText($object) {50$monogram = $object->getMonogram();51$title = $object->getTitle();5253$diff = $this->getDiff();54if ($diff) {55return pht('Update Revision %s: %s', $monogram, $title);56} else {57return pht('Edit Revision %s: %s', $monogram, $title);58}59}6061protected function getObjectEditShortText($object) {62return $object->getMonogram();63}6465public function getCreateURI($form_key) {66return '/differential/diff/create/';67}6869protected function getObjectCreateShortText() {70return pht('Create Revision');71}7273protected function getObjectName() {74return pht('Revision');75}7677protected function getCommentViewButtonText($object) {78if ($object->isDraft()) {79return pht('Submit Quietly');80}8182return parent::getCommentViewButtonText($object);83}8485protected function getObjectViewURI($object) {86return $object->getURI();87}8889protected function getEditorURI() {90return $this->getApplication()->getApplicationURI('revision/edit/');91}9293public function setDiff(DifferentialDiff $diff) {94$this->diff = $diff;95return $this;96}9798public function getDiff() {99return $this->diff;100}101102protected function newCommentActionGroups() {103return array(104id(new PhabricatorEditEngineCommentActionGroup())105->setKey(self::ACTIONGROUP_REVIEW)106->setLabel(pht('Review Actions')),107id(new PhabricatorEditEngineCommentActionGroup())108->setKey(self::ACTIONGROUP_REVISION)109->setLabel(pht('Revision Actions')),110);111}112113protected function buildCustomEditFields($object) {114$viewer = $this->getViewer();115116$plan_required = PhabricatorEnv::getEnvConfig(117'differential.require-test-plan-field');118$plan_enabled = $this->isCustomFieldEnabled(119$object,120'differential:test-plan');121122$diff = $this->getDiff();123if ($diff) {124$diff_phid = $diff->getPHID();125} else {126$diff_phid = null;127}128129$is_create = $this->getIsCreate();130$is_update = ($diff && !$is_create);131132$fields = array();133134$fields[] = id(new PhabricatorHandlesEditField())135->setKey(DifferentialRevisionUpdateTransaction::EDITKEY)136->setLabel(pht('Update Diff'))137->setDescription(pht('New diff to create or update the revision with.'))138->setConduitDescription(pht('Create or update a revision with a diff.'))139->setConduitTypeDescription(pht('PHID of the diff.'))140->setTransactionType(141DifferentialRevisionUpdateTransaction::TRANSACTIONTYPE)142->setHandleParameterType(new AphrontPHIDListHTTPParameterType())143->setSingleValue($diff_phid)144->setIsFormField((bool)$diff)145->setIsReorderable(false)146->setIsDefaultable(false)147->setIsInvisible(true)148->setIsLockable(false);149150if ($is_update) {151$fields[] = id(new PhabricatorInstructionsEditField())152->setKey('update.help')153->setValue(pht('Describe the updates you have made to the diff.'));154$fields[] = id(new PhabricatorCommentEditField())155->setKey('update.comment')156->setLabel(pht('Comment'))157->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)158->setIsWebOnly(true)159->setDescription(pht('Comments providing context for the update.'));160$fields[] = id(new PhabricatorSubmitEditField())161->setKey('update.submit')162->setValue($this->getObjectEditButtonText($object));163$fields[] = id(new PhabricatorDividerEditField())164->setKey('update.note');165}166167$fields[] = id(new PhabricatorTextEditField())168->setKey(DifferentialRevisionTitleTransaction::EDITKEY)169->setLabel(pht('Title'))170->setIsRequired(true)171->setTransactionType(172DifferentialRevisionTitleTransaction::TRANSACTIONTYPE)173->setDescription(pht('The title of the revision.'))174->setConduitDescription(pht('Retitle the revision.'))175->setConduitTypeDescription(pht('New revision title.'))176->setValue($object->getTitle());177178$author_field = id(new PhabricatorDatasourceEditField())179->setKey(DifferentialRevisionAuthorTransaction::EDITKEY)180->setLabel(pht('Author'))181->setDatasource(new PhabricatorPeopleDatasource())182->setTransactionType(183DifferentialRevisionAuthorTransaction::TRANSACTIONTYPE)184->setDescription(pht('Foist this revision upon someone else.'))185->setConduitDescription(pht('Foist this revision upon another user.'))186->setConduitTypeDescription(pht('New author.'))187->setSingleValue($object->getAuthorPHID());188189// Don't show the "Author" field when creating a revision using the web190// workflow, since it adds more noise than signal to this workflow.191if ($this->getIsCreate()) {192$author_field->setIsHidden(true);193}194195// Only show the "Foist Upon" comment action to the current revision196// author. Other users can use "Edit Revision", it's just very unlikley197// that they're interested in this action.198if ($viewer->getPHID() === $object->getAuthorPHID()) {199$author_field->setCommentActionLabel(pht('Foist Upon'));200}201202$fields[] = $author_field;203204$fields[] = id(new PhabricatorRemarkupEditField())205->setKey(DifferentialRevisionSummaryTransaction::EDITKEY)206->setLabel(pht('Summary'))207->setTransactionType(208DifferentialRevisionSummaryTransaction::TRANSACTIONTYPE)209->setDescription(pht('The summary of the revision.'))210->setConduitDescription(pht('Change the revision summary.'))211->setConduitTypeDescription(pht('New revision summary.'))212->setValue($object->getSummary());213214if ($plan_enabled) {215$fields[] = id(new PhabricatorRemarkupEditField())216->setKey(DifferentialRevisionTestPlanTransaction::EDITKEY)217->setLabel(pht('Test Plan'))218->setIsRequired($plan_required)219->setTransactionType(220DifferentialRevisionTestPlanTransaction::TRANSACTIONTYPE)221->setDescription(222pht('Actions performed to verify the behavior of the change.'))223->setConduitDescription(pht('Update the revision test plan.'))224->setConduitTypeDescription(pht('New test plan.'))225->setValue($object->getTestPlan());226}227228$fields[] = id(new PhabricatorDatasourceEditField())229->setKey(DifferentialRevisionReviewersTransaction::EDITKEY)230->setLabel(pht('Reviewers'))231->setDatasource(new DifferentialReviewerDatasource())232->setUseEdgeTransactions(true)233->setTransactionType(234DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE)235->setCommentActionLabel(pht('Change Reviewers'))236->setDescription(pht('Reviewers for this revision.'))237->setConduitDescription(pht('Change the reviewers for this revision.'))238->setConduitTypeDescription(pht('New reviewers.'))239->setValue($object->getReviewerPHIDsForEdit());240241$fields[] = id(new PhabricatorDatasourceEditField())242->setKey('repositoryPHID')243->setLabel(pht('Repository'))244->setDatasource(new DiffusionRepositoryDatasource())245->setTransactionType(246DifferentialRevisionRepositoryTransaction::TRANSACTIONTYPE)247->setDescription(pht('The repository the revision belongs to.'))248->setConduitDescription(pht('Change the repository for this revision.'))249->setConduitTypeDescription(pht('New repository.'))250->setSingleValue($object->getRepositoryPHID());251252// This is a little flimsy, but allows "Maniphest Tasks: ..." to continue253// working properly in commit messages until we fully sort out T5873.254$fields[] = id(new PhabricatorHandlesEditField())255->setKey('tasks')256->setUseEdgeTransactions(true)257->setIsFormField(false)258->setTransactionType(PhabricatorTransactions::TYPE_EDGE)259->setMetadataValue(260'edge:type',261DifferentialRevisionHasTaskEdgeType::EDGECONST)262->setDescription(pht('Tasks associated with this revision.'))263->setConduitDescription(pht('Change associated tasks.'))264->setConduitTypeDescription(pht('List of tasks.'))265->setValue(array());266267$fields[] = id(new PhabricatorHandlesEditField())268->setKey('parents')269->setUseEdgeTransactions(true)270->setIsFormField(false)271->setTransactionType(PhabricatorTransactions::TYPE_EDGE)272->setMetadataValue(273'edge:type',274DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST)275->setDescription(pht('Parent revisions of this revision.'))276->setConduitDescription(pht('Change associated parent revisions.'))277->setConduitTypeDescription(pht('List of revisions.'))278->setValue(array());279280$fields[] = id(new PhabricatorHandlesEditField())281->setKey('children')282->setUseEdgeTransactions(true)283->setIsFormField(false)284->setTransactionType(PhabricatorTransactions::TYPE_EDGE)285->setMetadataValue(286'edge:type',287DifferentialRevisionDependedOnByRevisionEdgeType::EDGECONST)288->setDescription(pht('Child revisions of this revision.'))289->setConduitDescription(pht('Change associated child revisions.'))290->setConduitTypeDescription(pht('List of revisions.'))291->setValue(array());292293$actions = DifferentialRevisionActionTransaction::loadAllActions();294$actions = msortv($actions, 'getRevisionActionOrderVector');295296foreach ($actions as $key => $action) {297$fields[] = $action->newEditField($object, $viewer);298}299300$fields[] = id(new PhabricatorBoolEditField())301->setKey('draft')302->setLabel(pht('Hold as Draft'))303->setIsFormField(false)304->setOptions(305pht('Autosubmit Once Builds Finish'),306pht('Hold as Draft'))307->setTransactionType(308DifferentialRevisionHoldDraftTransaction::TRANSACTIONTYPE)309->setDescription(pht('Hold revision as as draft.'))310->setConduitDescription(311pht(312'Change autosubmission from draft state after builds finish.'))313->setConduitTypeDescription(pht('New "Hold as Draft" setting.'))314->setValue($object->getHoldAsDraft());315316return $fields;317}318319private function isCustomFieldEnabled(DifferentialRevision $revision, $key) {320$field_list = PhabricatorCustomField::getObjectFields(321$revision,322PhabricatorCustomField::ROLE_VIEW);323324$fields = $field_list->getFields();325return isset($fields[$key]);326}327328protected function newAutomaticCommentTransactions($object) {329$viewer = $this->getViewer();330331$editor = $object->getApplicationTransactionEditor()332->setActor($viewer);333334$xactions = $editor->newAutomaticInlineTransactions(335$object,336DifferentialTransaction::TYPE_INLINE,337new DifferentialDiffInlineCommentQuery());338339return $xactions;340}341342protected function newCommentPreviewContent($object, array $xactions) {343$viewer = $this->getViewer();344$type_inline = DifferentialTransaction::TYPE_INLINE;345346$inlines = array();347foreach ($xactions as $xaction) {348if ($xaction->getTransactionType() === $type_inline) {349$inlines[] = $xaction->getComment();350}351}352353$content = array();354355if ($inlines) {356// Reload inlines to get inline context.357$inlines = id(new DifferentialDiffInlineCommentQuery())358->setViewer($viewer)359->withIDs(mpull($inlines, 'getID'))360->needInlineContext(true)361->execute();362363$inline_preview = id(new PHUIDiffInlineCommentPreviewListView())364->setViewer($viewer)365->setInlineComments($inlines);366367$content[] = phutil_tag(368'div',369array(370'id' => 'inline-comment-preview',371),372$inline_preview);373}374375return $content;376}377378379}380381382