mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Drive CLI-based revision edits through "differential.revision.edit" API + EditEngine
Summary: Ref T11114. This creates `differential.revision.edit` (a modern, v3 API method) and redefines the existing methods in terms of it. Both `differential.createrevision` and `differential.updaterevision` are now internally implemented by building a `differential.revision.edit` API call and then executing it. I //think// this covers everything except custom fields, which need some tweaking to work with EditEngine. I'll clean that up in the next change. Test Plan: - Created, updated, and edited revisions via `arc`. - Called APIs manually via test console. - Stored custom fields ("Blame Rev", "Revert Plan") aren't exposed yet. Reviewers: chad Reviewed By: chad Maniphest Tasks: T11114 Differential Revision: https://secure.phabricator.com/D17067
This commit is contained in:
parent
24926f9453
commit
64509dcca7
27 changed files with 231 additions and 98 deletions
|
@ -527,6 +527,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php',
|
||||
'DifferentialRevisionDependedOnByRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependedOnByRevisionEdgeType.php',
|
||||
'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php',
|
||||
'DifferentialRevisionEditConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php',
|
||||
'DifferentialRevisionEditEngine' => 'applications/differential/editor/DifferentialRevisionEditEngine.php',
|
||||
'DifferentialRevisionEditProController' => 'applications/differential/controller/DifferentialRevisionEditProController.php',
|
||||
'DifferentialRevisionFulltextEngine' => 'applications/differential/search/DifferentialRevisionFulltextEngine.php',
|
||||
|
@ -5203,6 +5204,7 @@ phutil_register_library_map(array(
|
|||
'DifferentialRevisionControlSystem' => 'Phobject',
|
||||
'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType',
|
||||
'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType',
|
||||
'DifferentialRevisionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
|
||||
'DifferentialRevisionEditEngine' => 'PhabricatorEditEngine',
|
||||
'DifferentialRevisionEditProController' => 'DifferentialController',
|
||||
'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||
|
|
|
@ -53,21 +53,16 @@ abstract class DifferentialConduitAPIMethod extends ConduitAPIMethod {
|
|||
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$revision,
|
||||
DifferentialCustomField::ROLE_COMMITMESSAGEEDIT);
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($revision);
|
||||
$field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit');
|
||||
// We're going to build the body of a "differential.revision.edit" API
|
||||
// request, then just call that code directly.
|
||||
|
||||
$xactions = array();
|
||||
$xactions[] = array(
|
||||
'type' => DifferentialRevisionEditEngine::KEY_UPDATE,
|
||||
'value' => $diff->getPHID(),
|
||||
);
|
||||
|
||||
$xactions[] = id(new DifferentialTransaction())
|
||||
->setTransactionType(DifferentialTransaction::TYPE_UPDATE)
|
||||
->setNewValue($diff->getPHID());
|
||||
|
||||
$field_map = DifferentialCommitMessageField::newEnabledFields($viewer);
|
||||
$values = $request->getValue('fields', array());
|
||||
foreach ($values as $key => $value) {
|
||||
$field = idx($field_map, $key);
|
||||
|
@ -79,53 +74,20 @@ abstract class DifferentialConduitAPIMethod extends ConduitAPIMethod {
|
|||
continue;
|
||||
}
|
||||
|
||||
$role = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS;
|
||||
if (!$field->shouldEnableForRole($role)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: This is fairly similar to PhabricatorCustomField's
|
||||
// buildFieldTransactionsFromRequest() method, but that's currently not
|
||||
// easy to reuse.
|
||||
|
||||
$transaction_type = $field->getApplicationTransactionType();
|
||||
$xaction = id(new DifferentialTransaction())
|
||||
->setTransactionType($transaction_type);
|
||||
|
||||
if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
|
||||
// For TYPE_CUSTOMFIELD transactions only, we provide the old value
|
||||
// as an input.
|
||||
$old_value = $field->getOldValueForApplicationTransactions();
|
||||
$xaction->setOldValue($old_value);
|
||||
}
|
||||
|
||||
// The transaction itself will be validated so this is somewhat
|
||||
// redundant, but this validator will sometimes give us a better error
|
||||
// message or a better reaction to a bad value type.
|
||||
$field->validateCommitMessageValue($value);
|
||||
$field->readValueFromCommitMessage($value);
|
||||
$value = $field->readFieldValueFromConduit($value);
|
||||
|
||||
$xaction
|
||||
->setNewValue($field->getNewValueForApplicationTransactions());
|
||||
|
||||
if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) {
|
||||
// For TYPE_CUSTOMFIELD transactions, add the field key in metadata.
|
||||
$xaction->setMetadataValue('customfield:key', $field->getFieldKey());
|
||||
foreach ($field->getFieldTransactions($value) as $xaction) {
|
||||
$xactions[] = $xaction;
|
||||
}
|
||||
|
||||
$metadata = $field->getApplicationTransactionMetadata();
|
||||
foreach ($metadata as $meta_key => $meta_value) {
|
||||
$xaction->setMetadataValue($meta_key, $meta_value);
|
||||
}
|
||||
|
||||
$xactions[] = $xaction;
|
||||
}
|
||||
|
||||
$message = $request->getValue('message');
|
||||
if (strlen($message)) {
|
||||
// This is a little awkward, and should maybe move inside the transaction
|
||||
// editor. It largely exists for legacy reasons. See some discussion in
|
||||
// T7899.
|
||||
// This is a little awkward, and should move elsewhere or be removed. It
|
||||
// largely exists for legacy reasons. See some discussion in T7899.
|
||||
$first_line = head(phutil_split_lines($message, false));
|
||||
|
||||
$first_line = id(new PhutilUTF8StringTruncator())
|
||||
|
@ -136,20 +98,24 @@ abstract class DifferentialConduitAPIMethod extends ConduitAPIMethod {
|
|||
$diff->setDescription($first_line);
|
||||
$diff->save();
|
||||
|
||||
$xactions[] = id(new DifferentialTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
|
||||
->attachComment(
|
||||
id(new DifferentialTransactionComment())
|
||||
->setContent($message));
|
||||
$xactions[] = array(
|
||||
'type' => PhabricatorCommentEditEngineExtension::EDITKEY,
|
||||
'value' => $message,
|
||||
);
|
||||
}
|
||||
|
||||
$editor = id(new DifferentialTransactionEditor())
|
||||
->setActor($viewer)
|
||||
->setContentSource($request->newContentSource())
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
$method = 'differential.revision.edit';
|
||||
$params = array(
|
||||
'transactions' => $xactions,
|
||||
);
|
||||
|
||||
$editor->applyTransactions($revision, $xactions);
|
||||
if ($revision->getID()) {
|
||||
$params['objectIdentifier'] = $revision->getID();
|
||||
}
|
||||
|
||||
return id(new ConduitCall($method, $params, $strict = true))
|
||||
->setUser($viewer)
|
||||
->execute();
|
||||
}
|
||||
|
||||
protected function loadCustomFieldsForRevisions(
|
||||
|
|
|
@ -45,16 +45,18 @@ final class DifferentialCreateRevisionConduitAPIMethod
|
|||
$revision = DifferentialRevision::initializeNewRevision($viewer);
|
||||
$revision->attachReviewerStatus(array());
|
||||
|
||||
$this->applyFieldEdit(
|
||||
$result = $this->applyFieldEdit(
|
||||
$request,
|
||||
$revision,
|
||||
$diff,
|
||||
$request->getValue('fields', array()),
|
||||
$message = null);
|
||||
|
||||
$revision_id = $result['object']['id'];
|
||||
|
||||
return array(
|
||||
'revisionid' => $revision->getID(),
|
||||
'uri' => PhabricatorEnv::getURI('/D'.$revision->getID()),
|
||||
'revisionid' => $revision_id,
|
||||
'uri' => PhabricatorEnv::getURI('/D'.$revision_id),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,15 @@ final class DifferentialGetCommitMessageConduitAPIMethod
|
|||
$revision = DifferentialRevision::initializeNewRevision($viewer);
|
||||
}
|
||||
|
||||
// There are three modes here: "edit", "create", and "read" (which has
|
||||
// no value for the "edit" parameter).
|
||||
|
||||
// In edit or create mode, we hide read-only fields. In create mode, we
|
||||
// show "Field:" templates for some fields even if they are empty.
|
||||
$edit_mode = $request->getValue('edit');
|
||||
|
||||
$is_any_edit = (bool)strlen($edit_mode);
|
||||
$is_create = ($edit_mode == 'create');
|
||||
$is_edit = ($edit_mode && !$is_create);
|
||||
|
||||
$field_list = DifferentialCommitMessageField::newEnabledFields($viewer);
|
||||
|
||||
|
@ -62,7 +68,7 @@ final class DifferentialGetCommitMessageConduitAPIMethod
|
|||
|
||||
// If we're editing the message, remove fields like "Conflicts" and
|
||||
// "git-svn-id" which should not be presented to the user for editing.
|
||||
if ($is_edit) {
|
||||
if ($is_any_edit) {
|
||||
foreach ($field_list as $field_key => $field) {
|
||||
if (!$field->isFieldEditable()) {
|
||||
unset($field_list[$field_key]);
|
||||
|
@ -96,7 +102,7 @@ final class DifferentialGetCommitMessageConduitAPIMethod
|
|||
$wire_value = $value_map[$field_key];
|
||||
$value = $field->renderFieldValue($wire_value);
|
||||
|
||||
$is_template = ($is_edit && $field->isTemplateField());
|
||||
$is_template = ($is_create && $field->isTemplateField());
|
||||
|
||||
if (!is_string($value) && !is_null($value)) {
|
||||
throw new Exception(
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class DifferentialRevisionEditConduitAPIMethod
|
||||
extends PhabricatorEditEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'differential.revision.edit';
|
||||
}
|
||||
|
||||
public function newEditEngine() {
|
||||
return new DifferentialRevisionEditEngine();
|
||||
}
|
||||
|
||||
public function getMethodSummary() {
|
||||
return pht('Apply transactions to create or update a revision.');
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,8 @@ final class DifferentialRevisionEditEngine
|
|||
|
||||
const ENGINECONST = 'differential.revision';
|
||||
|
||||
const KEY_UPDATE = 'update';
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Revisions');
|
||||
}
|
||||
|
@ -100,21 +102,20 @@ final class DifferentialRevisionEditEngine
|
|||
|
||||
$fields = array();
|
||||
|
||||
if ($diff || $is_create) {
|
||||
$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);
|
||||
}
|
||||
$fields[] = id(new PhabricatorHandlesEditField())
|
||||
->setKey(self::KEY_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)
|
||||
->setIsConduitOnly(!$diff)
|
||||
->setIsReorderable(false)
|
||||
->setIsDefaultable(false)
|
||||
->setIsInvisible(true)
|
||||
->setIsLockable(false);
|
||||
|
||||
if ($is_update) {
|
||||
$fields[] = id(new PhabricatorInstructionsEditField())
|
||||
|
@ -134,7 +135,7 @@ final class DifferentialRevisionEditEngine
|
|||
}
|
||||
|
||||
$fields[] = id(new PhabricatorTextEditField())
|
||||
->setKey('title')
|
||||
->setKey(DifferentialRevisionTitleTransaction::EDITKEY)
|
||||
->setLabel(pht('Title'))
|
||||
->setIsRequired(true)
|
||||
->setTransactionType(
|
||||
|
@ -145,7 +146,7 @@ final class DifferentialRevisionEditEngine
|
|||
->setValue($object->getTitle());
|
||||
|
||||
$fields[] = id(new PhabricatorRemarkupEditField())
|
||||
->setKey('summary')
|
||||
->setKey(DifferentialRevisionSummaryTransaction::EDITKEY)
|
||||
->setLabel(pht('Summary'))
|
||||
->setTransactionType(
|
||||
DifferentialRevisionSummaryTransaction::TRANSACTIONTYPE)
|
||||
|
@ -156,7 +157,7 @@ final class DifferentialRevisionEditEngine
|
|||
|
||||
if ($plan_enabled) {
|
||||
$fields[] = id(new PhabricatorRemarkupEditField())
|
||||
->setKey('testPlan')
|
||||
->setKey(DifferentialRevisionTestPlanTransaction::EDITKEY)
|
||||
->setLabel(pht('Test Plan'))
|
||||
->setIsRequired($plan_required)
|
||||
->setTransactionType(
|
||||
|
@ -169,7 +170,7 @@ final class DifferentialRevisionEditEngine
|
|||
}
|
||||
|
||||
$fields[] = id(new PhabricatorDatasourceEditField())
|
||||
->setKey('reviewerPHIDs')
|
||||
->setKey(DifferentialRevisionReviewersTransaction::EDITKEY)
|
||||
->setLabel(pht('Reviewers'))
|
||||
->setDatasource(new DifferentialReviewerDatasource())
|
||||
->setUseEdgeTransactions(true)
|
||||
|
|
|
@ -60,4 +60,9 @@ abstract class DifferentialCommitMessageCustomField
|
|||
return $idx;
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
// TODO: Implement this!
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,6 +67,13 @@ abstract class DifferentialCommitMessageField
|
|||
return $value;
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
if (!$this->isFieldEditable()) {
|
||||
return array();
|
||||
}
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
||||
final public function getCommitMessageFieldKey() {
|
||||
return $this->getPhobjectClassConstant('FIELDKEY', 64);
|
||||
}
|
||||
|
|
|
@ -17,4 +17,8 @@ final class DifferentialConflictsCommitMessageField
|
|||
return false;
|
||||
}
|
||||
|
||||
public function isTemplateField() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,4 +17,8 @@ final class DifferentialGitSVNIDCommitMessageField
|
|||
return false;
|
||||
}
|
||||
|
||||
public function isTemplateField() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ final class DifferentialReviewedByCommitMessageField
|
|||
return false;
|
||||
}
|
||||
|
||||
public function isTemplateField() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function readFieldValueFromObject(DifferentialRevision $revision) {
|
||||
if (!$revision->getPHID()) {
|
||||
return array();
|
||||
|
|
|
@ -77,6 +77,30 @@ final class DifferentialReviewersCommitMessageField
|
|||
return $this->renderHandleList($phid_list, $suffix_map);
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
$value = $this->inflateReviewers($value);
|
||||
|
||||
$reviewer_list = array();
|
||||
foreach ($value as $reviewer) {
|
||||
$phid = $reviewer['phid'];
|
||||
if (isset($reviewer['suffixes']['!'])) {
|
||||
$reviewer_list[] = 'blocking('.$phid.')';
|
||||
} else {
|
||||
$reviewer_list[] = $phid;
|
||||
}
|
||||
}
|
||||
|
||||
$xaction_key = DifferentialRevisionReviewersTransaction::EDITKEY;
|
||||
$xaction_type = "{$xaction_key}.set";
|
||||
|
||||
return array(
|
||||
array(
|
||||
'type' => $xaction_type,
|
||||
'value' => $reviewer_list,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function flattenReviewers(array $values) {
|
||||
// NOTE: For now, `arc` relies on this field returning only scalars, so we
|
||||
// need to reduce the results into scalars. See T10981.
|
||||
|
|
|
@ -76,4 +76,8 @@ final class DifferentialRevisionIDCommitMessageField
|
|||
return PhabricatorEnv::getProductionURI('/D'.$value);
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,4 +48,13 @@ final class DifferentialSubscribersCommitMessageField
|
|||
return $this->renderHandleList($value);
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array(
|
||||
array(
|
||||
'type' => PhabricatorSubscriptionsEditEngineExtension::EDITKEY_SET,
|
||||
'value' => $value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,4 +17,13 @@ final class DifferentialSummaryCommitMessageField
|
|||
return $revision->getSummary();
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array(
|
||||
array(
|
||||
'type' => DifferentialRevisionSummaryTransaction::EDITKEY,
|
||||
'value' => $value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,5 +54,13 @@ final class DifferentialTagsCommitMessageField
|
|||
return $this->renderHandleList($value);
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array(
|
||||
array(
|
||||
'type' => PhabricatorProjectsEditEngineExtension::EDITKEY_SET,
|
||||
'value' => $value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -54,4 +54,8 @@ final class DifferentialTasksCommitMessageField
|
|||
return $this->renderHandleList($value);
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
// TODO: Implement this!
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,4 +41,13 @@ final class DifferentialTestPlanCommitMessageField
|
|||
return $revision->getTestPlan();
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array(
|
||||
array(
|
||||
'type' => DifferentialRevisionTestPlanTransaction::EDITKEY,
|
||||
'value' => $value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,4 +47,13 @@ final class DifferentialTitleCommitMessageField
|
|||
return $value;
|
||||
}
|
||||
|
||||
public function getFieldTransactions($value) {
|
||||
return array(
|
||||
array(
|
||||
'type' => DifferentialRevisionTitleTransaction::EDITKEY,
|
||||
'value' => $value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ final class DifferentialRevisionReviewersTransaction
|
|||
extends DifferentialRevisionTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'differential.revision.reviewers';
|
||||
const EDITKEY = 'reviewers';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
$reviewers = $object->getReviewerStatus();
|
||||
|
@ -18,6 +19,7 @@ final class DifferentialRevisionReviewersTransaction
|
|||
->setViewer($actor);
|
||||
|
||||
$reviewers = $this->generateOldValue($object);
|
||||
$old_reviewers = $reviewers;
|
||||
|
||||
// First, remove any reviewers we're getting rid of.
|
||||
$rem = idx($value, '-', array());
|
||||
|
@ -63,7 +65,7 @@ final class DifferentialRevisionReviewersTransaction
|
|||
|
||||
$status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING;
|
||||
foreach ($add_map as $phid => $new_status) {
|
||||
$old_status = idx($reviewers, $phid);
|
||||
$old_status = idx($old_reviewers, $phid);
|
||||
|
||||
// If we have an old status and this didn't make the reviewer blocking
|
||||
// or nonblocking, just retain the old status. This makes sure we don't
|
||||
|
@ -76,6 +78,7 @@ final class DifferentialRevisionReviewersTransaction
|
|||
$is_unblock = (!$now_blocking && $was_blocking);
|
||||
|
||||
if (!$is_block && !$is_unblock) {
|
||||
$reviewers[$phid] = $old_status;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +89,14 @@ final class DifferentialRevisionReviewersTransaction
|
|||
return $reviewers;
|
||||
}
|
||||
|
||||
public function getTransactionHasEffect($object, $old, $new) {
|
||||
// At least for now, we ignore transactions which ONLY reorder reviewers
|
||||
// without making any actual changes.
|
||||
ksort($old);
|
||||
ksort($new);
|
||||
return ($old !== $new);
|
||||
}
|
||||
|
||||
public function applyExternalEffects($object, $value) {
|
||||
$src_phid = $object->getPHID();
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ final class DifferentialRevisionSummaryTransaction
|
|||
extends DifferentialRevisionTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'differential.revision.summary';
|
||||
const EDITKEY = 'summary';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getSummary();
|
||||
|
|
|
@ -4,6 +4,7 @@ final class DifferentialRevisionTestPlanTransaction
|
|||
extends DifferentialRevisionTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'differential.revision.testplan';
|
||||
const EDITKEY = 'testPlan';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getTestPlan();
|
||||
|
|
|
@ -4,6 +4,7 @@ final class DifferentialRevisionTitleTransaction
|
|||
extends DifferentialRevisionTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'differential.revision.title';
|
||||
const EDITKEY = 'title';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getTitle();
|
||||
|
|
|
@ -5,6 +5,10 @@ final class PhabricatorProjectsEditEngineExtension
|
|||
|
||||
const EXTENSIONKEY = 'projects.projects';
|
||||
|
||||
const EDITKEY_ADD = 'projects.add';
|
||||
const EDITKEY_SET = 'projects.set';
|
||||
const EDITKEY_REMOVE = 'projects.remove';
|
||||
|
||||
public function getExtensionPriority() {
|
||||
return 500;
|
||||
}
|
||||
|
@ -58,14 +62,14 @@ final class PhabricatorProjectsEditEngineExtension
|
|||
|
||||
$projects_field->setViewer($engine->getViewer());
|
||||
|
||||
$edit_add = $projects_field->getConduitEditType('projects.add')
|
||||
$edit_add = $projects_field->getConduitEditType(self::EDITKEY_ADD)
|
||||
->setConduitDescription(pht('Add project tags.'));
|
||||
|
||||
$edit_set = $projects_field->getConduitEditType('projects.set')
|
||||
$edit_set = $projects_field->getConduitEditType(self::EDITKEY_SET)
|
||||
->setConduitDescription(
|
||||
pht('Set project tags, overwriting current value.'));
|
||||
|
||||
$edit_rem = $projects_field->getConduitEditType('projects.remove')
|
||||
$edit_rem = $projects_field->getConduitEditType(self::EDITKEY_REMOVE)
|
||||
->setConduitDescription(pht('Remove project tags.'));
|
||||
|
||||
return array(
|
||||
|
|
|
@ -5,6 +5,10 @@ final class PhabricatorSubscriptionsEditEngineExtension
|
|||
|
||||
const EXTENSIONKEY = 'subscriptions.subscribers';
|
||||
|
||||
const EDITKEY_ADD = 'subscribers.add';
|
||||
const EDITKEY_SET = 'subscribers.set';
|
||||
const EDITKEY_REMOVE = 'subscribers.remove';
|
||||
|
||||
public function getExtensionPriority() {
|
||||
return 750;
|
||||
}
|
||||
|
@ -52,14 +56,14 @@ final class PhabricatorSubscriptionsEditEngineExtension
|
|||
|
||||
$subscribers_field->setViewer($engine->getViewer());
|
||||
|
||||
$edit_add = $subscribers_field->getConduitEditType('subscribers.add')
|
||||
$edit_add = $subscribers_field->getConduitEditType(self::EDITKEY_ADD)
|
||||
->setConduitDescription(pht('Add subscribers.'));
|
||||
|
||||
$edit_set = $subscribers_field->getConduitEditType('subscribers.set')
|
||||
$edit_set = $subscribers_field->getConduitEditType(self::EDITKEY_SET)
|
||||
->setConduitDescription(
|
||||
pht('Set subscribers, overwriting current value.'));
|
||||
|
||||
$edit_rem = $subscribers_field->getConduitEditType('subscribers.remove')
|
||||
$edit_rem = $subscribers_field->getConduitEditType(self::EDITKEY_REMOVE)
|
||||
->setConduitDescription(pht('Remove subscribers.'));
|
||||
|
||||
return array(
|
||||
|
|
|
@ -4,6 +4,7 @@ final class PhabricatorCommentEditEngineExtension
|
|||
extends PhabricatorEditEngineExtension {
|
||||
|
||||
const EXTENSIONKEY = 'transactions.comment';
|
||||
const EDITKEY = 'comment';
|
||||
|
||||
public function getExtensionPriority() {
|
||||
return 9000;
|
||||
|
@ -39,7 +40,7 @@ final class PhabricatorCommentEditEngineExtension
|
|||
$comment_type = PhabricatorTransactions::TYPE_COMMENT;
|
||||
|
||||
$comment_field = id(new PhabricatorCommentEditField())
|
||||
->setKey('comment')
|
||||
->setKey(self::EDITKEY)
|
||||
->setLabel(pht('Comments'))
|
||||
->setAliases(array('comments'))
|
||||
->setIsHidden(true)
|
||||
|
|
|
@ -396,13 +396,16 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
|||
if (!self::isFunctionToken($token)) {
|
||||
$results[] = $token;
|
||||
} else {
|
||||
$evaluate[] = $token;
|
||||
// Put a placeholder in the result list so that we retain token order
|
||||
// when possible. We'll overwrite this below.
|
||||
$results[] = null;
|
||||
$evaluate[last_key($results)] = $token;
|
||||
}
|
||||
}
|
||||
|
||||
$results = $this->evaluateValues($results);
|
||||
|
||||
foreach ($evaluate as $function) {
|
||||
foreach ($evaluate as $result_key => $function) {
|
||||
$function = self::parseFunction($function);
|
||||
if (!$function) {
|
||||
throw new PhabricatorTypeaheadInvalidTokenException();
|
||||
|
@ -411,11 +414,23 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
|||
$name = $function['name'];
|
||||
$argv = $function['argv'];
|
||||
|
||||
foreach ($this->evaluateFunction($name, array($argv)) as $phid) {
|
||||
$results[] = $phid;
|
||||
$evaluated_tokens = $this->evaluateFunction($name, array($argv));
|
||||
if (!$evaluated_tokens) {
|
||||
unset($results[$result_key]);
|
||||
} else {
|
||||
$is_first = true;
|
||||
foreach ($evaluated_tokens as $phid) {
|
||||
if ($is_first) {
|
||||
$results[$result_key] = $phid;
|
||||
$is_first = false;
|
||||
} else {
|
||||
$results[] = $phid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = array_values($results);
|
||||
$results = $this->didEvaluateTokens($results);
|
||||
|
||||
return $results;
|
||||
|
|
Loading…
Reference in a new issue