Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/fact/chart/PhabricatorComposeChartFunction.php
12256 views
1
<?php
2
3
final class PhabricatorComposeChartFunction
4
extends PhabricatorHigherOrderChartFunction {
5
6
const FUNCTIONKEY = 'compose';
7
8
protected function newArguments() {
9
return array(
10
$this->newArgument()
11
->setName('f')
12
->setType('function')
13
->setRepeatable(true),
14
);
15
}
16
17
public function evaluateFunction(array $xv) {
18
$original_positions = array_keys($xv);
19
$remaining_positions = $original_positions;
20
foreach ($this->getFunctionArguments() as $function) {
21
$xv = $function->evaluateFunction($xv);
22
23
// If a function evaluates to "null" at some positions, we want to return
24
// "null" at those positions and stop evaluating the function.
25
26
// We also want to pass "evaluateFunction()" a natural list containing
27
// only values it should evaluate: keys should not be important and we
28
// should not pass "null". This simplifies implementation of functions.
29
30
// To do this, first create a map from original input positions to
31
// function return values.
32
$xv = array_combine($remaining_positions, $xv);
33
34
// If a function evaluated to "null" at any position where we evaluated
35
// it, the result will be "null". We remove the position from the
36
// vector so we stop evaluating it.
37
foreach ($xv as $x => $y) {
38
if ($y !== null) {
39
continue;
40
}
41
42
unset($xv[$x]);
43
}
44
45
// Store the remaining original input positions for the next round, then
46
// throw away the array keys so we're passing the next function a natural
47
// list with only non-"null" values.
48
$remaining_positions = array_keys($xv);
49
$xv = array_values($xv);
50
51
// If we have no more inputs to evaluate, we can bail out early rather
52
// than passing empty vectors to functions for evaluation.
53
if (!$xv) {
54
break;
55
}
56
}
57
58
59
$yv = array();
60
$xv = array_combine($remaining_positions, $xv);
61
foreach ($original_positions as $position) {
62
if (isset($xv[$position])) {
63
$y = $xv[$position];
64
} else {
65
$y = null;
66
}
67
$yv[$position] = $y;
68
}
69
70
return $yv;
71
}
72
73
public function getDataRefs(array $xv) {
74
// TODO: This is not entirely correct. The correct implementation would
75
// map "x -> y" at each stage of composition and pull and aggregate all
76
// the datapoint refs. In practice, we currently never compose functions
77
// with a data function somewhere in the middle, so just grabbing the first
78
// result is close enough.
79
80
// In the future, we may: notably, "x -> shift(-1 month) -> ..." to
81
// generate a month-over-month overlay is a sensible operation which will
82
// source data from the middle of a function composition.
83
84
foreach ($this->getFunctionArguments() as $function) {
85
return $function->getDataRefs($xv);
86
}
87
88
return array();
89
}
90
91
}
92
93