@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 PhabricatorFactChartFunction
4 extends PhabricatorChartFunction {
5
6 const FUNCTIONKEY = 'fact';
7
8 private $fact;
9 private $map;
10 private $refs;
11
12 protected function newArguments() {
13 $key_argument = $this->newArgument()
14 ->setName('fact-key')
15 ->setType('fact-key');
16
17 $parser = $this->getArgumentParser();
18 $parser->parseArgument($key_argument);
19
20 $fact = $this->getArgument('fact-key');
21 $this->fact = $fact;
22
23 return $fact->getFunctionArguments();
24 }
25
26 public function loadData() {
27 $fact = $this->fact;
28
29 $key_id = id(new PhabricatorFactKeyDimension())
30 ->newDimensionID($fact->getKey());
31 if (!$key_id) {
32 $this->map = array();
33 return;
34 }
35
36 $table = $fact->newDatapoint();
37 $conn = $table->establishConnection('r');
38 $table_name = $table->getTableName();
39
40 $where = array();
41
42 $where[] = qsprintf(
43 $conn,
44 'keyID = %d',
45 $key_id);
46
47 $parser = $this->getArgumentParser();
48
49 $parts = $fact->buildWhereClauseParts($conn, $parser);
50 foreach ($parts as $part) {
51 $where[] = $part;
52 }
53
54 $data = queryfx_all(
55 $conn,
56 'SELECT id, value, epoch FROM %T WHERE %LA ORDER BY epoch ASC',
57 $table_name,
58 $where);
59
60 $map = array();
61 $refs = array();
62 if ($data) {
63 foreach ($data as $row) {
64 $ref = (string)$row['id'];
65 $value = (int)$row['value'];
66 $epoch = (int)$row['epoch'];
67
68 if (!isset($map[$epoch])) {
69 $map[$epoch] = 0;
70 }
71
72 $map[$epoch] += $value;
73
74 if (!isset($refs[$epoch])) {
75 $refs[$epoch] = array();
76 }
77
78 $refs[$epoch][] = $ref;
79 }
80 }
81
82 $this->map = $map;
83 $this->refs = $refs;
84 }
85
86 public function getDomain() {
87 $min = head_key($this->map);
88 $max = last_key($this->map);
89
90 return new PhabricatorChartInterval($min, $max);
91 }
92
93 public function newInputValues(PhabricatorChartDataQuery $query) {
94 return array_keys($this->map);
95 }
96
97 public function evaluateFunction(array $xv) {
98 $map = $this->map;
99
100 $yv = array();
101
102 foreach ($xv as $x) {
103 if (isset($map[$x])) {
104 $yv[] = $map[$x];
105 } else {
106 $yv[] = null;
107 }
108 }
109
110 return $yv;
111 }
112
113 public function getDataRefs(array $xv) {
114 return array_select_keys($this->refs, $xv);
115 }
116
117 public function loadRefs(array $refs) {
118 $fact = $this->fact;
119
120 $datapoint_table = $fact->newDatapoint();
121 $conn = $datapoint_table->establishConnection('r');
122
123 $dimension_table = new PhabricatorFactObjectDimension();
124
125 $where = array();
126
127 $where[] = qsprintf(
128 $conn,
129 'p.id IN (%Ld)',
130 $refs);
131
132
133 $rows = queryfx_all(
134 $conn,
135 'SELECT
136 p.id id,
137 p.value,
138 od.objectPHID objectPHID,
139 dd.objectPHID dimensionPHID
140 FROM %R p
141 LEFT JOIN %R od ON od.id = p.objectID
142 LEFT JOIN %R dd ON dd.id = p.dimensionID
143 WHERE %LA',
144 $datapoint_table,
145 $dimension_table,
146 $dimension_table,
147 $where);
148 $rows = ipull($rows, null, 'id');
149
150 $results = array();
151
152 foreach ($refs as $ref) {
153 if (!isset($rows[$ref])) {
154 continue;
155 }
156
157 $row = $rows[$ref];
158
159 $results[$ref] = array(
160 'objectPHID' => $row['objectPHID'],
161 'dimensionPHID' => $row['dimensionPHID'],
162 'value' => (float)$row['value'],
163 );
164 }
165
166 return $results;
167 }
168
169}