diff --git a/src/applications/differential/field/specification/maniphesttasks/DifferentialManiphestTasksFieldSpecification.php b/src/applications/differential/field/specification/maniphesttasks/DifferentialManiphestTasksFieldSpecification.php index 3f2f9d4b8a..bd1f9c298d 100644 --- a/src/applications/differential/field/specification/maniphesttasks/DifferentialManiphestTasksFieldSpecification.php +++ b/src/applications/differential/field/specification/maniphesttasks/DifferentialManiphestTasksFieldSpecification.php @@ -19,6 +19,8 @@ final class DifferentialManiphestTasksFieldSpecification extends DifferentialFieldSpecification { + private $maniphestTasks = array(); + public function shouldAppearOnRevisionView() { return PhabricatorEnv::getEnvConfig('maniphest.enabled'); } @@ -51,4 +53,124 @@ final class DifferentialManiphestTasksFieldSpecification PhabricatorPHIDConstants::PHID_TYPE_TASK); } + /** + * Attach the revision to the task(s) and the task(s) to the revision. + * + * @return void + */ + public function willWriteRevision(DifferentialRevisionEditor $editor) { + // 1 -- revision => tasks + $revision = $editor->getRevision(); + $revision->setAttachedPHIDs(PhabricatorPHIDConstants::PHID_TYPE_TASK, + $this->maniphestTasks); + + // 2 -- tasks => revision + $maniphest_editor = new ManiphestTransactionEditor(); + $user = $this->getUser(); + $type = ManiphestTransactionType::TYPE_ATTACH; + $attach_type = PhabricatorPHIDConstants::PHID_TYPE_DREV; + $attach_data = array($revision->getPHID() => array()); + + $tasks = id(new ManiphestTask()) + ->loadAllWhere('phid IN (%Ld)', $this->maniphestTasks); + + foreach ($tasks as $task) { + $transaction = new ManiphestTransaction(); + $transaction->setAuthorPHID($user->getPHID()); + $transaction->setTransactionType($type); + + $new = $task->getAttached(); + $new[$attach_type] = $attach_data; + + $transaction->setNewValue($new); + $maniphest_editor->applyTransactions($task, array($transaction)); + } + } + + protected function didSetRevision() { + $this->maniphestTasks = $this->getManiphestTaskPHIDs(); + } + + public function getRequiredHandlePHIDsForCommitMessage() { + return $this->maniphestTasks; + } + + public function shouldAppearOnCommitMessageTemplate() { + return PhabricatorEnv::getEnvConfig('maniphest.enabled'); + } + + public function shouldAppearOnCommitMessage() { + return PhabricatorEnv::getEnvConfig('maniphest.enabled'); + } + + public function getCommitMessageKey() { + return 'maniphestTaskPHIDs'; + } + + public function setValueFromParsedCommitMessage($value) { + $this->maniphestTasks = nonempty($value, array()); + return $this; + } + + public function renderLabelForCommitMessage() { + return 'Maniphest Tasks'; + } + + public function getSupportedCommitMessageLabels() { + return array( + 'Maniphest Task', + 'Maniphest Tasks', + ); + } + + public function renderValueForCommitMessage($is_edit) { + if (!$this->maniphestTasks) { + return null; + } + + $names = array(); + foreach ($this->maniphestTasks as $phid) { + $handle = $this->getHandle($phid); + $names[] = 'T'.$handle->getAlternateID(); + } + return implode(', ', $names); + } + + public function parseValueFromCommitMessage($value) { + $matches = null; + preg_match_all('/T(\d+)/', $value, $matches); + if (empty($matches[0])) { + return array(); + } + + + $task_ids = $matches[1]; + $tasks = id(new ManiphestTask()) + ->loadAllWhere('id in (%Ld)', $task_ids); + + $task_phids = array(); + $invalid = array(); + foreach ($task_ids as $task_id) { + $task = idx($tasks, $task_id); + if (empty($task)) { + $invalid[] = 'T'.$task_id; + } else { + $task_phids[] = $task->getPHID(); + } + } + + if ($invalid) { + if (count($invalid) > 1) { + $what = 'Maniphest Tasks'; + } else { + $what = 'Maniphest Task'; + } + $invalid = implode(', ', $invalid); + throw new DifferentialFieldParseException( + "Commit message references nonexistent {$what}: {$invalid}."); + } + + return $task_phids; + } + } diff --git a/src/applications/differential/field/specification/maniphesttasks/__init__.php b/src/applications/differential/field/specification/maniphesttasks/__init__.php index 54c0ba2d66..4f9b037319 100644 --- a/src/applications/differential/field/specification/maniphesttasks/__init__.php +++ b/src/applications/differential/field/specification/maniphesttasks/__init__.php @@ -6,9 +6,16 @@ +phutil_require_module('phabricator', 'applications/differential/field/exception/parse'); phutil_require_module('phabricator', 'applications/differential/field/specification/base'); +phutil_require_module('phabricator', 'applications/maniphest/constants/transactiontype'); +phutil_require_module('phabricator', 'applications/maniphest/editor/transaction'); +phutil_require_module('phabricator', 'applications/maniphest/storage/task'); +phutil_require_module('phabricator', 'applications/maniphest/storage/transaction'); phutil_require_module('phabricator', 'applications/phid/constants'); phutil_require_module('phabricator', 'infrastructure/env'); +phutil_require_module('phutil', 'utils'); + phutil_require_source('DifferentialManiphestTasksFieldSpecification.php'); diff --git a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php index 91bf8096ea..74d9a433da 100644 --- a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php +++ b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php @@ -296,6 +296,7 @@ class PhabricatorObjectHandleData { $handle->setURI('/T'.$task->getID()); $handle->setFullName('T'.$task->getID().': '.$task->getTitle()); $handle->setComplete(true); + $handle->setAlternateID($task->getID()); if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) { $closed = PhabricatorObjectHandleStatus::STATUS_CLOSED; $handle->setStatus($closed);