3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * Build various graphs using the dc chart library.
21 class CRM_Utils_Chart
{
27 private static $_colours = [
43 * Build The Bar Gharph.
45 * @param array $params
46 * Assoc array of name/value pairs.
49 * $chart object data used for client-side chart rendering (currently with dc chart library).
51 public static function barChart($params) {
52 $output = static::commonParamsManipulation($params);
56 $output['type'] = 'barchart';
58 $output +
= ['title' => ts('Bar Chart')];
60 // ? Not sure what reports use this, but it's not implemented.
61 // call user define function to handle on click event.
62 // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
63 // $bars[$barCount]->set_on_click($onClickFunName);
66 //// get the currency to set in tooltip.
67 //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
75 * @param array $params
76 * Assoc array of name/value pairs.
80 public static function pieChart($params) {
81 $output = static::commonParamsManipulation($params);
85 $output['type'] = 'piechart';
86 $output +
= ['title' => ts('Pie Chart')];
88 // ? Not sure what reports use this, but it's not implemented.
89 // call user define function to handle on click event.
90 // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
91 // $bars[$barCount]->set_on_click($onClickFunName);
94 //// get the currency to set in tooltip.
95 //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
101 * Common data manipulation for charts.
103 * @param array $params
104 * Assoc array of name/value pairs.
108 public static function commonParamsManipulation($params) {
109 if (empty($params)) {
113 if (empty($params['multiValues'])) {
114 $params['multiValues'] = [$params['values']];
117 $output['values'] = [];
118 foreach ($params['multiValues'] as $i => $dataSet) {
119 $output['values'][$i] = [];
120 foreach ($dataSet as $k => $v) {
121 $output['values'][$i][] = ['label' => $k, 'value' => (double) $v];
124 if (!$output['values']) {
128 // Ensure there's a legend (title)
129 if (!empty($params['legend'])) {
130 $output['title'] = $params['legend'];
133 $output['symbol'] = CRM_Core_BAO_Country
::defaultCurrencySymbol();
135 // ? Not sure what reports use this, but it's not implemented.
136 // call user define function to handle on click event.
137 // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
138 // $bars[$barCount]->set_on_click($onClickFunName);
141 //// get the currency to set in tooltip.
142 //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
154 public static function chart($rows, $chart, $interval) {
155 $lcInterval = strtolower($interval);
156 $label = ucfirst($lcInterval);
157 $chartData = $dateKeys = [];
159 'year' => ts('Yearly'),
160 'fiscalyear' => ts('Yearly (Fiscal)'),
161 'month' => ts('Monthly'),
162 'quarter' => ts('Quarterly'),
163 'week' => ts('Weekly'),
164 'yearweek' => ts('Weekly'),
167 switch ($lcInterval) {
172 foreach ($rows['receive_date'] as $key => $val) {
173 list($year, $month) = explode('-', $val);
174 $dateKeys[] = substr($rows[$interval][$key], 0, 3) . ' of ' . $year;
176 $legend = $intervalLabels[$lcInterval];
180 foreach ($rows['receive_date'] as $key => $val) {
181 list($year, $month) = explode('-', $val);
184 $legend = ts("%1", [1 => $label]);
185 if (!empty($intervalLabels[$lcInterval])) {
186 $legend = $intervalLabels[$lcInterval];
191 if (!empty($dateKeys)) {
193 if (!array_key_exists('multiValue', $rows)) {
194 $rows['multiValue'] = [$rows['value']];
196 foreach ($rows['multiValue'] as $key => $val) {
197 $graph[$key] = array_combine($dateKeys, $rows['multiValue'][$key]);
200 'legend' => "$legend " . CRM_Utils_Array
::value('legend', $rows, ts('Contribution')) . ' ' . ts('Summary'),
201 'values' => $graph[0],
202 'multiValues' => $graph,
203 'barKeys' => $rows['barKeys'] ??
[],
207 // rotate the x labels.
208 $chartData['xLabelAngle'] = $rows['xLabelAngle'] ??
0;
209 if (!empty($rows['tip'])) {
210 $chartData['tip'] = $rows['tip'];
214 $chartData['xname'] = $rows['xname'] ??
NULL;
215 $chartData['yname'] = $rows['yname'] ??
NULL;
217 // carry some chart params if pass.
223 if (!empty($rows[$f])) {
224 $chartData[$f] = $rows[$f];
228 return self
::buildChart($chartData, $chart);
239 public static function reportChart($rows, $chart, $interval, &$chartInfo) {
240 foreach ($interval as $key => $val) {
241 $graph[$val] = $rows['value'][$key];
246 'legend' => $chartInfo['legend'],
247 'xname' => $chartInfo['xname'],
248 'yname' => $chartInfo['yname'],
251 // rotate the x labels.
252 $chartData['xLabelAngle'] = CRM_Utils_Array
::value('xLabelAngle', $chartInfo, 20);
253 if (!empty($chartInfo['tip'])) {
254 $chartData['tip'] = $chartInfo['tip'];
257 // carry some chart params if pass.
263 if (!empty($rows[$f])) {
264 $chartData[$f] = $rows[$f];
268 return self
::buildChart($chartData, $chart);
272 * @param array $params
277 public static function buildChart(&$params, $chart) {
279 if ($chart && is_array($params) && !empty($params)) {
280 // build the chart objects.
281 $chartObj = CRM_Utils_Chart
::$chart($params);
284 // calculate chart size.
285 $xSize = CRM_Utils_Array
::value('xSize', $params, 400);
286 $ySize = CRM_Utils_Array
::value('ySize', $params, 300);
287 if ($chart == 'barChart') {
288 $ySize = CRM_Utils_Array
::value('ySize', $params, 250);
289 $xSize = 60 * count($params['values']);
290 // hack to show tooltip.
292 $xSize = (count($params['values']) > 1) ?
100 * count($params['values']) : 170;
294 elseif ($xSize > 600 && count($params['values']) > 1) {
295 $xSize = (count($params['values']) +
400 / count($params['values'])) * count($params['values']);
299 // generate unique id for this chart instance
300 $uniqueId = md5(uniqid(rand(), TRUE));
302 $theChart["chart_{$uniqueId}"]['size'] = ['xSize' => $xSize, 'ySize' => $ySize];
303 $theChart["chart_{$uniqueId}"]['object'] = $chartObj;
305 // assign chart data to template
306 $template = CRM_Core_Smarty
::singleton();
307 $template->assign('uniqueId', $uniqueId);
308 $template->assign("chartData", json_encode($theChart ??
[]));