Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/fact/controller/PhabricatorFactObjectController.php
12256 views
1
<?php
2
3
final class PhabricatorFactObjectController
4
extends PhabricatorFactController {
5
6
public function handleRequest(AphrontRequest $request) {
7
$viewer = $request->getViewer();
8
9
$phid = $request->getURIData('phid');
10
$object = id(new PhabricatorObjectQuery())
11
->setViewer($viewer)
12
->withNames(array($phid))
13
->executeOne();
14
if (!$object) {
15
return new Aphront404Response();
16
}
17
18
$engines = PhabricatorFactEngine::loadAllEngines();
19
foreach ($engines as $key => $engine) {
20
$engine = id(clone $engine)
21
->setViewer($viewer);
22
$engines[$key] = $engine;
23
24
if (!$engine->supportsDatapointsForObject($object)) {
25
unset($engines[$key]);
26
}
27
}
28
29
if (!$engines) {
30
return $this->newDialog()
31
->setTitle(pht('No Engines'))
32
->appendParagraph(
33
pht(
34
'No fact engines support generating facts for this object.'))
35
->addCancelButton($this->getApplicationURI());
36
}
37
38
$key_dimension = new PhabricatorFactKeyDimension();
39
$object_phid = $object->getPHID();
40
41
$facts = array();
42
$generated_datapoints = array();
43
$timings = array();
44
foreach ($engines as $key => $engine) {
45
$engine_facts = $engine->newFacts();
46
$engine_facts = mpull($engine_facts, null, 'getKey');
47
$facts[$key] = $engine_facts;
48
49
$t_start = microtime(true);
50
$generated_datapoints[$key] = $engine->newDatapointsForObject($object);
51
$t_end = microtime(true);
52
53
$timings[$key] = ($t_end - $t_start);
54
}
55
56
$object_id = id(new PhabricatorFactObjectDimension())
57
->newDimensionID($object_phid, true);
58
59
$stored_datapoints = id(new PhabricatorFactDatapointQuery())
60
->withFacts(array_mergev($facts))
61
->withObjectPHIDs(array($object_phid))
62
->needVectors(true)
63
->execute();
64
65
$stored_groups = array();
66
foreach ($stored_datapoints as $stored_datapoint) {
67
$stored_groups[$stored_datapoint['key']][] = $stored_datapoint;
68
}
69
70
$stored_map = array();
71
foreach ($engines as $key => $engine) {
72
$stored_map[$key] = array();
73
foreach ($facts[$key] as $fact) {
74
$fact_datapoints = idx($stored_groups, $fact->getKey(), array());
75
$fact_datapoints = igroup($fact_datapoints, 'vector');
76
$stored_map[$key] += $fact_datapoints;
77
}
78
}
79
80
$handle_phids = array();
81
$handle_phids[] = $object->getPHID();
82
foreach ($generated_datapoints as $key => $datapoint_set) {
83
foreach ($datapoint_set as $datapoint) {
84
$dimension_phid = $datapoint->getDimensionPHID();
85
if ($dimension_phid !== null) {
86
$handle_phids[$dimension_phid] = $dimension_phid;
87
}
88
}
89
}
90
91
foreach ($stored_map as $key => $stored_datapoints) {
92
foreach ($stored_datapoints as $vector_key => $datapoints) {
93
foreach ($datapoints as $datapoint) {
94
$dimension_phid = $datapoint['dimensionPHID'];
95
if ($dimension_phid !== null) {
96
$handle_phids[$dimension_phid] = $dimension_phid;
97
}
98
}
99
}
100
}
101
102
$handles = $viewer->loadHandles($handle_phids);
103
104
$dimension_map = id(new PhabricatorFactObjectDimension())
105
->newDimensionMap($handle_phids, true);
106
107
$content = array();
108
109
$object_list = id(new PHUIPropertyListView())
110
->setViewer($viewer)
111
->addProperty(
112
pht('Object'),
113
$handles[$object->getPHID()]->renderLink());
114
115
$total_cost = array_sum($timings);
116
$total_cost = pht('%sms', new PhutilNumber((int)(1000 * $total_cost)));
117
$object_list->addProperty(pht('Total Cost'), $total_cost);
118
119
$object_box = id(new PHUIObjectBoxView())
120
->setHeaderText(pht('Fact Extraction Report'))
121
->addPropertyList($object_list);
122
123
$content[] = $object_box;
124
125
$icon_fact = id(new PHUIIconView())
126
->setIcon('fa-line-chart green')
127
->setTooltip(pht('Consistent Fact'));
128
129
$icon_nodata = id(new PHUIIconView())
130
->setIcon('fa-question-circle-o violet')
131
->setTooltip(pht('No Stored Datapoints'));
132
133
$icon_new = id(new PHUIIconView())
134
->setIcon('fa-plus red')
135
->setTooltip(pht('Not Stored'));
136
137
$icon_surplus = id(new PHUIIconView())
138
->setIcon('fa-minus red')
139
->setTooltip(pht('Not Generated'));
140
141
foreach ($engines as $key => $engine) {
142
$rows = array();
143
foreach ($generated_datapoints[$key] as $datapoint) {
144
$dimension_phid = $datapoint->getDimensionPHID();
145
if ($dimension_phid !== null) {
146
$dimension = $handles[$datapoint->getDimensionPHID()]->renderLink();
147
} else {
148
$dimension = null;
149
}
150
151
$fact_key = $datapoint->getKey();
152
153
$fact = idx($facts[$key], $fact_key, null);
154
if ($fact) {
155
$fact_label = $fact->getName();
156
} else {
157
$fact_label = $fact_key;
158
}
159
160
$vector_key = $datapoint->newDatapointVector();
161
if (isset($stored_map[$key][$vector_key])) {
162
unset($stored_map[$key][$vector_key]);
163
$icon = $icon_fact;
164
} else {
165
$icon = $icon_new;
166
}
167
168
$rows[] = array(
169
$icon,
170
$fact_label,
171
$dimension,
172
$datapoint->getValue(),
173
phabricator_datetime($datapoint->getEpoch(), $viewer),
174
);
175
}
176
177
foreach ($stored_map[$key] as $vector_key => $datapoints) {
178
foreach ($datapoints as $datapoint) {
179
$dimension_phid = $datapoint['dimensionPHID'];
180
if ($dimension_phid !== null) {
181
$dimension = $handles[$dimension_phid]->renderLink();
182
} else {
183
$dimension = null;
184
}
185
186
$fact_key = $datapoint['key'];
187
$fact = idx($facts[$key], $fact_key, null);
188
if ($fact) {
189
$fact_label = $fact->getName();
190
} else {
191
$fact_label = $fact_key;
192
}
193
194
$rows[] = array(
195
$icon_surplus,
196
$fact_label,
197
$dimension,
198
$datapoint['value'],
199
phabricator_datetime($datapoint['epoch'], $viewer),
200
);
201
}
202
}
203
204
foreach ($facts[$key] as $fact) {
205
$has_any = id(new PhabricatorFactDatapointQuery())
206
->withFacts(array($fact))
207
->setLimit(1)
208
->execute();
209
if ($has_any) {
210
continue;
211
}
212
213
if (!$has_any) {
214
$rows[] = array(
215
$icon_nodata,
216
$fact->getName(),
217
null,
218
null,
219
null,
220
);
221
}
222
}
223
224
$table = id(new AphrontTableView($rows))
225
->setHeaders(
226
array(
227
null,
228
pht('Fact'),
229
pht('Dimension'),
230
pht('Value'),
231
pht('Date'),
232
))
233
->setColumnClasses(
234
array(
235
'',
236
'',
237
'',
238
'n wide right',
239
'right',
240
));
241
242
$extraction_cost = $timings[$key];
243
$extraction_cost = pht(
244
'%sms',
245
new PhutilNumber((int)(1000 * $extraction_cost)));
246
247
$header = pht(
248
'%s (%s)',
249
get_class($engine),
250
$extraction_cost);
251
252
$box = id(new PHUIObjectBoxView())
253
->setHeaderText($header)
254
->setTable($table);
255
256
$content[] = $box;
257
258
if ($engine instanceof PhabricatorTransactionFactEngine) {
259
$groups = $engine->newTransactionGroupsForObject($object);
260
$groups = array_values($groups);
261
262
$xaction_phids = array();
263
foreach ($groups as $group_key => $xactions) {
264
foreach ($xactions as $xaction) {
265
$xaction_phids[] = $xaction->getAuthorPHID();
266
}
267
}
268
$xaction_handles = $viewer->loadHandles($xaction_phids);
269
270
$rows = array();
271
foreach ($groups as $group_key => $xactions) {
272
foreach ($xactions as $xaction) {
273
$rows[] = array(
274
$group_key,
275
$xaction->getTransactionType(),
276
$xaction_handles[$xaction->getAuthorPHID()]->renderLink(),
277
phabricator_datetime($xaction->getDateCreated(), $viewer),
278
);
279
}
280
}
281
282
$table = id(new AphrontTableView($rows))
283
->setHeaders(
284
array(
285
pht('Group'),
286
pht('Type'),
287
pht('Author'),
288
pht('Date'),
289
))
290
->setColumnClasses(
291
array(
292
null,
293
'pri',
294
'wide',
295
'right',
296
));
297
298
$header = pht(
299
'%s (Transactions)',
300
get_class($engine));
301
302
$xaction_box = id(new PHUIObjectBoxView())
303
->setHeaderText($header)
304
->setTable($table);
305
306
$content[] = $xaction_box;
307
}
308
309
}
310
311
$crumbs = $this->buildApplicationCrumbs()
312
->addTextCrumb(pht('Chart'));
313
314
$title = pht('Chart');
315
316
return $this->newPage()
317
->setTitle($title)
318
->setCrumbs($crumbs)
319
->appendChild($content);
320
321
}
322
323
}
324
325