diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php --- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php +++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php @@ -1537,8 +1537,7 @@ PhabricatorProject $parent = null, $is_milestone = false) { - $project = PhabricatorProject::initializeNewProject($user); - + $project = PhabricatorProject::initializeNewProject($user, $parent); $name = pht('Test Project %d', mt_rand()); diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -336,6 +336,15 @@ $type_edge = PhabricatorTransactions::TYPE_EDGE; $edgetype_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; + // See T13462. If we're creating a milestone, set a dummy milestone + // number so the project behaves like a milestone and uses milestone + // policy rules. Otherwise, we'll end up checking the default policies + // (which are not relevant to milestones) instead of the parent project + // policies (which are the correct policies). + if ($this->getIsMilestone() && !$copy->isMilestone()) { + $copy->setMilestoneNumber(1); + } + $member_xaction = null; foreach ($xactions as $xaction) { if ($xaction->getTransactionType() !== $type_edge) { diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -107,7 +107,7 @@ ->setHasMilestones(0) ->setHasSubprojects(0) ->setSubtype(PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT) - ->attachParentProject(null); + ->attachParentProject($parent); } public function getCapabilities() {