@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 ManiphestTaskGraph
4 extends PhabricatorObjectGraph {
5
6 private $seedMaps = array();
7 private $isStandalone;
8
9 protected function getEdgeTypes() {
10 return array(
11 ManiphestTaskDependedOnByTaskEdgeType::EDGECONST,
12 ManiphestTaskDependsOnTaskEdgeType::EDGECONST,
13 );
14 }
15
16 protected function getParentEdgeType() {
17 return ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
18 }
19
20 protected function newQuery() {
21 return new ManiphestTaskQuery();
22 }
23
24 protected function isClosed($object) {
25 return $object->isClosed();
26 }
27
28 public function setIsStandalone($is_standalone) {
29 $this->isStandalone = $is_standalone;
30 return $this;
31 }
32
33 public function getIsStandalone() {
34 return $this->isStandalone;
35 }
36
37 protected function newTableRow($phid, $object, $trace) {
38 $viewer = $this->getViewer();
39
40 Javelin::initBehavior('phui-hovercards');
41
42 if ($object) {
43 $status = $object->getStatus();
44 $priority = $object->getPriority();
45 $status_icon = ManiphestTaskStatus::getStatusIcon($status);
46 $status_name = ManiphestTaskStatus::getTaskStatusName($status);
47
48 $priority_color = ManiphestTaskPriority::getTaskPriorityColor($priority);
49 if ($object->isClosed()) {
50 $priority_color = 'grey';
51 }
52
53 $status = array(
54 id(new PHUIIconView())->setIcon($status_icon, $priority_color),
55 ' ',
56 $status_name,
57 );
58
59 $owner_phid = $object->getOwnerPHID();
60 if ($owner_phid) {
61 $assigned = $viewer->renderHandle($owner_phid);
62 } else {
63 $assigned = phutil_tag('em', array(), pht('None'));
64 }
65
66 $link = javelin_tag(
67 'a',
68 array(
69 'href' => $object->getURI(),
70 'sigil' => 'hovercard',
71 'meta' => array(
72 'hovercardSpec' => array(
73 'objectPHID' => $object->getPHID(),
74 ),
75 ),
76 ),
77 $object->getTitle());
78
79 $link = array(
80 phutil_tag(
81 'span',
82 array(
83 'class' => 'object-name',
84 ),
85 $object->getMonogram()),
86 ' ',
87 $link,
88 );
89
90 $subtype_tag = null;
91
92 $subtype = $object->newSubtypeObject();
93 if ($subtype && $subtype->hasTagView()) {
94 $subtype_tag = $subtype->newTagView()
95 ->setSlimShady(true);
96 }
97 } else {
98 $status = null;
99 $assigned = null;
100 $subtype_tag = null;
101 $link = $viewer->renderHandle($phid);
102 }
103
104 if ($this->isParentTask($phid)) {
105 $marker = 'fa-chevron-circle-up bluegrey';
106 $marker_tip = pht('Direct Parent');
107 } else if ($this->isChildTask($phid)) {
108 $marker = 'fa-chevron-circle-down bluegrey';
109 $marker_tip = pht('Direct Subtask');
110 } else {
111 $marker = null;
112 }
113
114 if ($marker) {
115 $marker = id(new PHUIIconView())
116 ->setIcon($marker)
117 ->addSigil('has-tooltip')
118 ->setMetadata(
119 array(
120 'tip' => $marker_tip,
121 'align' => 'E',
122 ));
123 }
124
125 return array(
126 $marker,
127 $trace,
128 $status,
129 $subtype_tag,
130 $assigned,
131 $link,
132 );
133 }
134
135 protected function newTable(AphrontTableView $table) {
136 $subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap();
137 $has_subtypes = ($subtype_map->getCount() > 1);
138
139 return $table
140 ->setHeaders(
141 array(
142 null,
143 null,
144 pht('Status'),
145 pht('Subtype'),
146 pht('Assigned'),
147 pht('Task'),
148 ))
149 ->setColumnClasses(
150 array(
151 'nudgeright',
152 'threads',
153 'graph-status',
154 null,
155 null,
156 'wide pri object-link',
157 ))
158 ->setColumnVisibility(
159 array(
160 true,
161 !$this->getRenderOnlyAdjacentNodes(),
162 true,
163 $has_subtypes,
164 ))
165 ->setDeviceVisibility(
166 array(
167 true,
168
169 // On mobile, we only show the actual graph drawing if we're on the
170 // standalone page, since it can take over the screen otherwise.
171 $this->getIsStandalone(),
172 true,
173
174 // On mobile, don't show subtypes since they're relatively less
175 // important and we're more pressured for space.
176 false,
177 ));
178 }
179
180 private function isParentTask($task_phid) {
181 $map = $this->getSeedMap(ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);
182 return isset($map[$task_phid]);
183 }
184
185 private function isChildTask($task_phid) {
186 $map = $this->getSeedMap(ManiphestTaskDependsOnTaskEdgeType::EDGECONST);
187 return isset($map[$task_phid]);
188 }
189
190 private function getSeedMap($type) {
191 if (!isset($this->seedMaps[$type])) {
192 $maps = $this->getEdges($type);
193 $phids = idx($maps, $this->getSeedPHID(), array());
194 $phids = array_fuse($phids);
195 $this->seedMaps[$type] = $phids;
196 }
197
198 return $this->seedMaps[$type];
199 }
200
201 protected function newEllipsisRow() {
202 return array(
203 null,
204 null,
205 null,
206 null,
207 null,
208 pht("\xC2\xB7 \xC2\xB7 \xC2\xB7"),
209 );
210 }
211
212
213}