@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorProjectEditController
4 extends PhabricatorProjectController {
5
6 private $engine;
7
8 public function setEngine(PhabricatorProjectEditEngine $engine) {
9 $this->engine = $engine;
10 return $this;
11 }
12
13 public function getEngine() {
14 return $this->engine;
15 }
16
17 public function handleRequest(AphrontRequest $request) {
18 $viewer = $this->getViewer();
19
20 $engine = id(new PhabricatorProjectEditEngine())
21 ->setController($this);
22
23 $this->setEngine($engine);
24
25 $id = $request->getURIData('id');
26 if (!$id) {
27 // This capability is checked again later, but checking it here
28 // explicitly gives us a better error message.
29 $this->requireApplicationCapability(
30 ProjectCreateProjectsCapability::CAPABILITY);
31
32 $parent_id = head($request->getArr('parent'));
33 if (!$parent_id) {
34 $parent_id = $request->getStr('parent');
35 }
36
37 if ($parent_id) {
38 $is_milestone = false;
39 } else {
40 $parent_id = head($request->getArr('milestone'));
41 if (!$parent_id) {
42 $parent_id = $request->getStr('milestone');
43 }
44 $is_milestone = true;
45 }
46
47 if ($parent_id) {
48 $query = id(new PhabricatorProjectQuery())
49 ->setViewer($viewer)
50 ->needImages(true)
51 ->requireCapabilities(
52 array(
53 PhabricatorPolicyCapability::CAN_VIEW,
54 PhabricatorPolicyCapability::CAN_EDIT,
55 ));
56
57 if (ctype_digit($parent_id)) {
58 $query->withIDs(array($parent_id));
59 } else {
60 $query->withPHIDs(array($parent_id));
61 }
62
63 $parent = $query->executeOne();
64
65 if ($is_milestone) {
66 if (!$parent->supportsMilestones()) {
67 $cancel_uri = "/project/subprojects/{$parent_id}/";
68 return $this->newDialog()
69 ->setTitle(pht('No Milestones'))
70 ->appendParagraph(
71 pht('You can not add milestones to this project.'))
72 ->addCancelButton($cancel_uri);
73 }
74 $engine->setMilestoneProject($parent);
75 } else {
76 if (!$parent->supportsSubprojects()) {
77 $cancel_uri = "/project/subprojects/{$parent_id}/";
78 return $this->newDialog()
79 ->setTitle(pht('No Subprojects'))
80 ->appendParagraph(
81 pht('You can not add subprojects to this project.'))
82 ->addCancelButton($cancel_uri);
83 }
84 $engine->setParentProject($parent);
85 }
86
87 $this->setProject($parent);
88 }
89 }
90
91 return $engine->buildResponse();
92 }
93
94 protected function buildApplicationCrumbs() {
95 $crumbs = parent::buildApplicationCrumbs();
96
97 $engine = $this->getEngine();
98 if ($engine) {
99 $parent = $engine->getParentProject();
100 $milestone = $engine->getMilestoneProject();
101 if ($parent || $milestone) {
102 $id = nonempty($parent, $milestone)->getID();
103 $crumbs->addTextCrumb(
104 pht('Subprojects'),
105 $this->getApplicationURI("subprojects/{$id}/"));
106 }
107 }
108
109 return $crumbs;
110 }
111
112}