. */ declare(strict_types=1); namespace FireflyIII\Generator\Chart\Basic; use FireflyIII\Support\ChartColour; /** * Class ChartJsGenerator. */ class ChartJsGenerator implements GeneratorInterface { /** * Expects data as:. * * key => [value => x, 'currency_symbol' => 'x'] * * @param array $data * * @return array */ public function multiCurrencyPieChart(array $data): array { $chartData = [ 'datasets' => [ 0 => [], ], 'labels' => [], ]; $amounts = array_column($data, 'amount'); $next = next($amounts); $sortFlag = SORT_ASC; if (!is_bool($next) && 1 === bccomp((string)$next, '0')) { $sortFlag = SORT_DESC; } array_multisort($amounts, $sortFlag, $data); unset($next, $sortFlag, $amounts); $index = 0; foreach ($data as $key => $valueArray) { // make larger than 0 $chartData['datasets'][0]['data'][] = (float)app('steam')->positive((string)$valueArray['amount']); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol']; $chartData['labels'][] = $key; ++$index; } return $chartData; } /** * Will generate a Chart JS compatible array from the given input. Expects this format. * * Will take labels for all from first set. * * 0: [ * 'label' => 'label of set', * 'type' => bar or line, optional * 'yAxisID' => ID of yAxis, optional, will not be included when unused. * 'fill' => if to fill a line? optional, will not be included when unused. * 'currency_symbol' => 'x', * 'backgroundColor' => 'x', * 'entries' => * [ * 'label-of-entry' => 'value' * ] * ] * 1: [ * 'label' => 'label of another set', * 'type' => bar or line, optional * 'yAxisID' => ID of yAxis, optional, will not be included when unused. * 'fill' => if to fill a line? optional, will not be included when unused. * 'entries' => * [ * 'label-of-entry' => 'value' * ] * ] * * // it's five. * * @param array $data * * @return array */ public function multiSet(array $data): array { reset($data); $first = current($data); if (!is_array($first)) { return []; } $labels = is_array($first['entries']) ? array_keys($first['entries']) : []; $chartData = [ 'count' => count($data), 'labels' => $labels, // take ALL labels from the first set. 'datasets' => [], ]; unset($first, $labels); foreach ($data as $set) { $currentSet = [ 'label' => $set['label'], 'type' => $set['type'] ?? 'line', 'data' => array_values($set['entries']), ]; if (array_key_exists('yAxisID', $set)) { $currentSet['yAxisID'] = $set['yAxisID']; } if (array_key_exists('fill', $set)) { $currentSet['fill'] = $set['fill']; } if (array_key_exists('currency_symbol', $set)) { $currentSet['currency_symbol'] = $set['currency_symbol']; } if (array_key_exists('backgroundColor', $set)) { $currentSet['backgroundColor'] = $set['backgroundColor']; } $chartData['datasets'][] = $currentSet; } return $chartData; } /** * Expects data as:. * * key => value * * @param array $data * * @return array */ public function pieChart(array $data): array { $chartData = [ 'datasets' => [ 0 => [], ], 'labels' => [], ]; // sort by value, keep keys. // different sort when values are positive and when they're negative. asort($data); $next = next($data); if (!is_bool($next) && 1 === bccomp((string)$next, '0')) { // next is positive, sort other way around. arsort($data); } unset($next); $index = 0; foreach ($data as $key => $value) { // make larger than 0 $chartData['datasets'][0]['data'][] = (float)app('steam')->positive((string)$value); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['labels'][] = $key; ++$index; } return $chartData; } /** * Will generate a (ChartJS) compatible array from the given input. Expects this format:. * * 'label-of-entry' => value * * @param string $setLabel * @param array $data * * @return array */ public function singleSet(string $setLabel, array $data): array { return [ 'count' => 1, 'labels' => array_keys($data), // take ALL labels from the first set. 'datasets' => [ [ 'label' => $setLabel, 'data' => array_values($data), ], ], ]; } }