diff --git a/src/applications/project/engine/PhabricatorProjectEditEngine.php b/src/applications/project/engine/PhabricatorProjectEditEngine.php --- a/src/applications/project/engine/PhabricatorProjectEditEngine.php +++ b/src/applications/project/engine/PhabricatorProjectEditEngine.php @@ -128,6 +128,19 @@ if (isset($unavailable[$xaction_type])) { unset($fields[$key]); } + // Paste previous milestone description as default when creating next + if ($this->getIsCreate() && + $field instanceof PhabricatorCustomFieldEditField && + $field->getLabel() === 'Description' ) { + $default_desc_text = $this->getPreviousMilestoneDescription(); + if (phutil_nonempty_string($default_desc_text)) { + $field->setValue($default_desc_text); + $field->setControlInstructions( + pht('Description text below was copied from the previous '. + 'milestone for convenience. Please update/remove the text.')); + } + break; + } } } @@ -320,7 +333,44 @@ } return $fields; + } + /** + * Get the description of the previous milestone project in the series + * @return string|null Description text of previous milestone + */ + private function getPreviousMilestoneDescription() { + $milestone = $this->getMilestoneProject(); + if ($milestone) { + $number = ($milestone->loadNextMilestoneNumber() - 1); + if ($number > 0) { + $previous_milestone = id(new PhabricatorProjectQuery()) + ->setViewer($this->getViewer()) + ->withParentProjectPHIDs(array($milestone->getPHID())) + ->withIsMilestone(true) + ->withMilestoneNumberBetween($number, $number) + ->executeOne(); + if ($previous_milestone) { + $desc_field = PhabricatorCustomField::getObjectField( + $previous_milestone, + PhabricatorCustomField::ROLE_VIEW, + 'std:project:internal:description'); + if ($desc_field) { + $viewer = $this->getViewer(); + $desc_field + ->setViewer($viewer) + ->readValueFromObject($previous_milestone); + id(new PhabricatorCustomFieldStorageQuery()) + ->addField($desc_field) + ->execute(); + if (phutil_nonempty_string($desc_field->getValueForStorage())) { + return $desc_field->getValueForStorage(); + } + } + } + } + } + return null; } }