diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2649,6 +2649,7 @@ 'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php', 'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php', 'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', + 'PhabricatorChartFunction' => 'applications/fact/function/PhabricatorChartFunction.php', 'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php', 'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php', 'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php', @@ -3203,6 +3204,7 @@ 'PhabricatorFactApplication' => 'applications/fact/application/PhabricatorFactApplication.php', 'PhabricatorFactChart' => 'applications/fact/storage/PhabricatorFactChart.php', 'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php', + 'PhabricatorFactChartFunction' => 'applications/fact/function/PhabricatorFactChartFunction.php', 'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php', 'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php', 'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php', @@ -8619,6 +8621,7 @@ 'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', + 'PhabricatorChartFunction' => 'Phobject', 'PhabricatorChatLogApplication' => 'PhabricatorApplication', 'PhabricatorChatLogChannel' => array( 'PhabricatorChatLogDAO', @@ -9235,6 +9238,7 @@ 'PhabricatorPolicyInterface', ), 'PhabricatorFactChartController' => 'PhabricatorFactController', + 'PhabricatorFactChartFunction' => 'PhabricatorChartFunction', 'PhabricatorFactController' => 'PhabricatorController', 'PhabricatorFactCursor' => 'PhabricatorFactDAO', 'PhabricatorFactDAO' => 'PhabricatorLiskDAO', diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php --- a/src/applications/fact/controller/PhabricatorFactChartController.php +++ b/src/applications/fact/controller/PhabricatorFactChartController.php @@ -12,81 +12,38 @@ $is_chart_mode = ($mode === 'chart'); $is_draw_mode = ($mode === 'draw'); - $series = $request->getStr('y1'); + $functions = array(); - $facts = PhabricatorFact::getAllFacts(); - $fact = idx($facts, $series); + $functions[] = id(new PhabricatorFactChartFunction()) + ->setArguments(array('tasks.count.create')); - if (!$fact) { - return new Aphront404Response(); - } - - $key_id = id(new PhabricatorFactKeyDimension()) - ->newDimensionID($fact->getKey()); - if (!$key_id) { - return new Aphront404Response(); - } + $functions[] = id(new PhabricatorFactChartFunction()) + ->setArguments(array('tasks.open-count.create')); if ($is_chart_mode) { return $this->newChartResponse(); } - $table = $fact->newDatapoint(); - $conn_r = $table->establishConnection('r'); - $table_name = $table->getTableName(); - - $data = queryfx_all( - $conn_r, - 'SELECT value, epoch FROM %T WHERE keyID = %d ORDER BY epoch ASC', - $table_name, - $key_id); - - $points = array(); - $sum = 0; - foreach ($data as $key => $row) { - $sum += (int)$row['value']; - $points[(int)$row['epoch']] = $sum; - } + $datasets = array(); + foreach ($functions as $function) { + $function->loadData(); - if (!$points) { - throw new Exception('No data to show!'); - } + $points = $function->getDatapoints(2000); - // Limit amount of data passed to browser. - $count = count($points); - $limit = 2000; - if ($count > $limit) { - $i = 0; - $every = ceil($count / $limit); - foreach ($points as $epoch => $sum) { - $i++; - if ($i % $every && $i != $count) { - unset($points[$epoch]); - } - } - } - - $datasets = array(); + $x = array(); + $y = array(); - $datasets[] = array( - 'x' => array_keys($points), - 'y' => array_values($points), - 'color' => '#ff0000', - ); + foreach ($points as $point) { + $x[] = $point['x']; + $y[] = $point['y']; + } - // Add a dummy "y = x" dataset to prove we can draw multiple datasets. - $x_min = min(array_keys($points)); - $x_max = max(array_keys($points)); - $x_range = ($x_max - $x_min) / 4; - $linear = array(); - foreach ($points as $x => $y) { - $linear[$x] = round(count($points) * (($x - $x_min) / $x_range)); + $datasets[] = array( + 'x' => $x, + 'y' => $y, + 'color' => '#ff00ff', + ); } - $datasets[] = array( - 'x' => array_keys($linear), - 'y' => array_values($linear), - 'color' => '#0000ff', - ); $y_min = 0; $y_max = 0; diff --git a/src/applications/fact/function/PhabricatorChartFunction.php b/src/applications/fact/function/PhabricatorChartFunction.php new file mode 100644 --- /dev/null +++ b/src/applications/fact/function/PhabricatorChartFunction.php @@ -0,0 +1,24 @@ +getPhobjectClassConstant('FUNCTIONKEY', 32); + } + + final public static function getAllFunctions() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getFunctionKey') + ->execute(); + } + + final public function setArguments(array $arguments) { + $this->newArguments($arguments); + return $this; + } + + abstract protected function newArguments(array $arguments); + +} diff --git a/src/applications/fact/function/PhabricatorFactChartFunction.php b/src/applications/fact/function/PhabricatorFactChartFunction.php new file mode 100644 --- /dev/null +++ b/src/applications/fact/function/PhabricatorFactChartFunction.php @@ -0,0 +1,102 @@ +factKey = $arguments[0]; + $this->fact = $fact; + } + + public function loadData() { + $fact = $this->fact; + + $key_id = id(new PhabricatorFactKeyDimension()) + ->newDimensionID($fact->getKey()); + if (!$key_id) { + return; + } + + $table = $fact->newDatapoint(); + $conn = $table->establishConnection('r'); + $table_name = $table->getTableName(); + + $data = queryfx_all( + $conn, + 'SELECT value, epoch FROM %T WHERE keyID = %d ORDER BY epoch ASC', + $table_name, + $key_id); + if (!$data) { + return; + } + + $points = array(); + + $sum = 0; + foreach ($data as $key => $row) { + $sum += (int)$row['value']; + $points[] = array( + 'x' => (int)$row['epoch'], + 'y' => $sum, + ); + } + + $this->datapoints = $points; + } + + public function getDatapoints($limit) { + $points = $this->datapoints; + if (!$points) { + return array(); + } + + // If we have too many data points, throw away some of the data. + $count = count($points); + if ($count > $limit) { + $ii = 0; + $every = ceil($count / $limit); + foreach ($points as $key => $point) { + $ii++; + if (($ii % $every) && ($ii != $count)) { + unset($points[$key]); + } + } + } + + return $points; + } + +}