Merge pull request #1433 from totten/master-validate-messages
[civicrm-core.git] / CRM / Utils / OpenFlashChart.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36 require_once 'packages/OpenFlashChart/php-ofc-library/open-flash-chart.php';
37
38 /**
39 * Build various graphs using Open Flash Chart library.
40 */
41 class CRM_Utils_OpenFlashChart {
42
43 /**
44 * colours.
45 * @var array
46 * @static
47 */
48 private static $_colours = array(
49 "#C3CC38", "#C8B935", "#CEA632", "#D3932F",
50 "#D9802C", "#FA6900", "#DC9B57", "#F78F01",
51 "#5AB56E", "#6F8069", "#C92200", "#EB6C5C",
52 );
53
54 /**
55 * Build The Bar Gharph.
56 *
57 * @param array $params assoc array of name/value pairs
58 *
59 * @return object $chart object of open flash chart.
60 * @static
61 */
62 static function &barChart(&$params) {
63 $chart = NULL;
64 if (empty($params)) {
65 return $chart;
66 }
67
68 $values = CRM_Utils_Array::value('values', $params);
69 if (!is_array($values) || empty($values)) {
70 return $chart;
71 }
72
73 // get the required data.
74 $xValues = $yValues = array();
75 foreach ($values as $xVal => $yVal) {
76 $yValues[] = (double)$yVal;
77
78 // we has to have x values as string.
79 $xValues[] = (string)$xVal;
80 }
81 $chartTitle = CRM_Utils_Array::value('legend', $params) ? $params['legend'] : ts('Bar Chart');
82
83 //set y axis parameters.
84 $yMin = 0;
85
86 // calculate max scale for graph.
87 $yMax = ceil(max($yValues));
88 if ($mod = $yMax % (str_pad(5, strlen($yMax) - 1, 0))) {
89 $yMax += str_pad(5, strlen($yMax) - 1, 0) - $mod;
90 }
91 $ySteps = $yMax / 5;
92
93 // $bar = new bar( );
94 // glass seem to be more cool
95 $bar = new bar_glass();
96
97 //set values.
98 $bar->set_values($yValues);
99
100 // call user define function to handle on click event.
101 if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
102 $bar->set_on_click($onClickFunName);
103 }
104
105 // get the currency.
106 $config = CRM_Core_Config::singleton();
107 $symbol = $config->defaultCurrencySymbol;
108
109 // set the tooltip.
110 $tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
111 $bar->set_tooltip($tooltip);
112
113 // create x axis label obj.
114 $xLabels = new x_axis_labels();
115 $xLabels->set_labels($xValues);
116
117 // set angle for labels.
118 if ($xLabelAngle = CRM_Utils_Array::value('xLabelAngle', $params)) {
119 $xLabels->rotate($xLabelAngle);
120 }
121
122 // create x axis obj.
123 $xAxis = new x_axis();
124 $xAxis->set_labels($xLabels);
125
126 //create y axis and set range.
127 $yAxis = new y_axis();
128 $yAxis->set_range($yMin, $yMax, $ySteps);
129
130 // create chart title obj.
131 $title = new title($chartTitle);
132
133 // create chart.
134 $chart = new open_flash_chart();
135
136 // add x axis w/ labels to chart.
137 $chart->set_x_axis($xAxis);
138
139 // add y axis values to chart.
140 $chart->add_y_axis($yAxis);
141
142 // set title to chart.
143 $chart->set_title($title);
144
145 // add bar element to chart.
146 $chart->add_element($bar);
147
148 // add x axis legend.
149 if ($xName = CRM_Utils_Array::value('xname', $params)) {
150 $xLegend = new x_legend($xName);
151 $xLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
152 $chart->set_x_legend($xLegend);
153 }
154
155 // add y axis legend.
156 if ($yName = CRM_Utils_Array::value('yname', $params)) {
157 $yLegend = new y_legend($yName);
158 $yLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
159 $chart->set_y_legend($yLegend);
160 }
161
162 return $chart;
163 }
164
165 /**
166 * Build The Pie Gharph.
167 *
168 * @param array $params assoc array of name/value pairs
169 *
170 * @return object $chart object of open flash chart.
171 * @static
172 */
173 static function &pieChart(&$params) {
174 $chart = NULL;
175 if (empty($params)) {
176 return $chart;
177 }
178 $allValues = CRM_Utils_Array::value('values', $params);
179 if (!is_array($allValues) || empty($allValues)) {
180 return $chart;
181 }
182
183 // get the required data.
184 $values = array();
185 foreach ($allValues as $label => $value) {
186 $values[] = new pie_value((double)$value, $label);
187 }
188 $graphTitle = CRM_Utils_Array::value('legend', $params) ? $params['legend'] : ts('Pie Chart');
189
190 //get the currency.
191 $config = CRM_Core_Config::singleton();
192 $symbol = $config->defaultCurrencySymbol;
193
194 $pie = new pie();
195 $pie->radius(100);
196
197 // call user define function to handle on click event.
198 if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
199 $pie->on_click($onClickFunName);
200 }
201
202 $pie->set_start_angle(35);
203 $pie->add_animation(new pie_fade());
204 $pie->add_animation(new pie_bounce(2));
205
206 // set the tooltip.
207 $tooltip = CRM_Utils_Array::value('tip', $params, "Amount is $symbol #val# of $symbol #total# <br>#percent#");
208 $pie->set_tooltip($tooltip);
209
210 // set colours.
211 $pie->set_colours(self::$_colours);
212
213 $pie->set_values($values);
214
215 //create chart.
216 $chart = new open_flash_chart();
217
218 // create chart title obj.
219 $title = new title($graphTitle);
220 $chart->set_title($title);
221
222 $chart->add_element($pie);
223 $chart->x_axis = NULL;
224
225 return $chart;
226 }
227
228 /**
229 * Build The 3-D Bar Gharph.
230 *
231 * @param array $params assoc array of name/value pairs
232 *
233 * @return object $chart object of open flash chart.
234 * @static
235 */
236 static function &bar_3dChart(&$params) {
237 $chart = NULL;
238 if (empty($params)) {
239 return $chart;
240 }
241
242 // $params['values'] should contains the values for each
243 // criteria defined in $params['criteria']
244 $values = CRM_Utils_Array::value('values', $params);
245 $criterias = CRM_Utils_Array::value('criteria', $params);
246 if (!is_array($values) || empty($values) || !is_array($criterias) || empty($criterias)) {
247 return $chart;
248 }
249
250 // get the required data.
251 $xReferences = $xValueLabels = $xValues = $yValues = array();
252
253 foreach ($values as $xVal => $yVal) {
254 if (!is_array($yVal) || empty($yVal)) {
255 continue;
256 }
257
258 $xValueLabels[] = (string)$xVal;
259 foreach ($criterias as $criteria) {
260 $xReferences[$criteria][$xVal] = (double)CRM_Utils_Array::value($criteria, $yVal, 0);
261 $yValues[] = (double)CRM_Utils_Array::value($criteria, $yVal, 0);
262 }
263 }
264
265 if (empty($xReferences)) {
266
267 return $chart;
268
269 }
270
271 // get the currency.
272 $config = CRM_Core_Config::singleton();
273 $symbol = $config->defaultCurrencySymbol;
274
275 // set the tooltip.
276 $tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
277
278 $count = 0;
279 foreach ($xReferences as $criteria => $values) {
280 $toolTipVal = $tooltip;
281 // for seperate tooltip for each criteria
282 if (is_array($tooltip)) {
283 $toolTipVal = CRM_Utils_Array::value($criteria, $tooltip, "$symbol #val#");
284 }
285
286 // create bar_3d object
287 $xValues[$count] = new bar_3d();
288 // set colour pattel
289 $xValues[$count]->set_colour(self::$_colours[$count]);
290 // define colur pattel with bar criterias
291 $xValues[$count]->key((string)$criteria, 12);
292 // define bar chart values
293 $xValues[$count]->set_values(array_values($values));
294
295 // set tooltip
296 $xValues[$count]->set_tooltip($toolTipVal);
297 $count++;
298 }
299
300 $chartTitle = CRM_Utils_Array::value('legend', $params) ? $params['legend'] : ts('Bar Chart');
301
302 //set y axis parameters.
303 $yMin = 0;
304
305 // calculate max scale for graph.
306 $yMax = ceil(max($yValues));
307 if ($mod = $yMax % (str_pad(5, strlen($yMax) - 1, 0))) {
308 $yMax += str_pad(5, strlen($yMax) - 1, 0) - $mod;
309 }
310
311 // if max value of y-axis <= 0, then set default values
312 if ($yMax <= 0) {
313 $ySteps = 1;
314 $yMax = 5;
315 }
316 else {
317 $ySteps = $yMax / 5;
318 }
319
320 // create x axis label obj.
321 $xLabels = new x_axis_labels();
322 $xLabels->set_labels($xValueLabels);
323
324 // set angle for labels.
325 if ($xLabelAngle = CRM_Utils_Array::value('xLabelAngle', $params)) {
326 $xLabels->rotate($xLabelAngle);
327 }
328
329 // create x axis obj.
330 $xAxis = new x_axis();
331 $xAxis->set_labels($xLabels);
332
333 //create y axis and set range.
334 $yAxis = new y_axis();
335 $yAxis->set_range($yMin, $yMax, $ySteps);
336
337 // create chart title obj.
338 $title = new title($chartTitle);
339
340 // create chart.
341 $chart = new open_flash_chart();
342
343 // add x axis w/ labels to chart.
344 $chart->set_x_axis($xAxis);
345
346 // add y axis values to chart.
347 $chart->add_y_axis($yAxis);
348
349 // set title to chart.
350 $chart->set_title($title);
351
352 foreach ($xValues as $bar) {
353 // add bar element to chart.
354 $chart->add_element($bar);
355 }
356
357 // add x axis legend.
358 if ($xName = CRM_Utils_Array::value('xname', $params)) {
359 $xLegend = new x_legend($xName);
360 $xLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
361 $chart->set_x_legend($xLegend);
362 }
363
364 // add y axis legend.
365 if ($yName = CRM_Utils_Array::value('yname', $params)) {
366 $yLegend = new y_legend($yName);
367 $yLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
368 $chart->set_y_legend($yLegend);
369 }
370
371 return $chart;
372 }
373
374 static function chart($rows, $chart, $interval) {
375 $chartData = array();
376
377 switch ($interval) {
378 case 'Month':
379 foreach ($rows['receive_date'] as $key => $val) {
380 list($year, $month) = explode('-', $val);
381 $graph[substr($rows['Month'][$key], 0, 3) . ' ' . $year] = $rows['value'][$key];
382 }
383
384 $chartData = array(
385 'values' => $graph,
386 'legend' => ts('Monthly Contribution Summary'),
387 );
388 break;
389
390 case 'Quarter':
391 foreach ($rows['receive_date'] as $key => $val) {
392 list($year, $month) = explode('-', $val);
393 $graph['Quarter ' . $rows['Quarter'][$key] . ' of ' . $year] = $rows['value'][$key];
394 }
395
396 $chartData = array(
397 'values' => $graph,
398 'legend' => ts('Quarterly Contribution Summary'),
399 );
400 break;
401
402 case 'Week':
403 foreach ($rows['receive_date'] as $key => $val) {
404 list($year, $month) = explode('-', $val);
405 $graph['Week ' . $rows['Week'][$key] . ' of ' . $year] = $rows['value'][$key];
406 }
407
408 $chartData = array(
409 'values' => $graph,
410 'legend' => ts('Weekly Contribution Summary'),
411 );
412 break;
413
414 case 'Year':
415 foreach ($rows['receive_date'] as $key => $val) {
416 list($year, $month) = explode('-', $val);
417 $graph[$year] = $rows['value'][$key];
418 }
419 $chartData = array(
420 'values' => $graph,
421 'legend' => ts('Yearly Contribution Summary'),
422 );
423 break;
424 }
425
426 // rotate the x labels.
427 $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $rows, 20);
428 if (CRM_Utils_Array::value('tip', $rows)) {
429 $chartData['tip'] = $rows['tip'];
430 }
431
432 //legend
433 $chartData['xname'] = CRM_Utils_Array::value('xname', $rows);
434 $chartData['yname'] = CRM_Utils_Array::value('yname', $rows);
435
436 // carry some chart params if pass.
437 foreach (array(
438 'xSize', 'ySize', 'divName') as $f) {
439 if (CRM_Utils_Array::value($f, $rows)) {
440 $chartData[$f] = $rows[$f];
441 }
442 }
443
444 return self::buildChart($chartData, $chart);
445 }
446
447 static function reportChart($rows, $chart, $interval, &$chartInfo) {
448 foreach ($interval as $key => $val) {
449 $graph[$val] = $rows['value'][$key];
450 }
451
452 $chartData = array(
453 'values' => $graph,
454 'legend' => $chartInfo['legend'],
455 'xname' => $chartInfo['xname'],
456 'yname' => $chartInfo['yname'],
457 );
458
459 // rotate the x labels.
460 $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $chartInfo, 20);
461 if (CRM_Utils_Array::value('tip', $chartInfo)) {
462 $chartData['tip'] = $chartInfo['tip'];
463 }
464
465 // carry some chart params if pass.
466 foreach (array(
467 'xSize', 'ySize', 'divName') as $f) {
468 if (CRM_Utils_Array::value($f, $rows)) {
469 $chartData[$f] = $rows[$f];
470 }
471 }
472
473 return self::buildChart($chartData, $chart);
474 }
475
476 static function buildChart(&$params, $chart) {
477 $openFlashChart = array();
478 if ($chart && is_array($params) && !empty($params)) {
479 // build the chart objects.
480 $chartObj = CRM_Utils_OpenFlashChart::$chart($params);
481
482 $openFlashChart = array();
483 if ($chartObj) {
484 // calculate chart size.
485 $xSize = CRM_Utils_Array::value('xSize', $params, 400);
486 $ySize = CRM_Utils_Array::value('ySize', $params, 300);
487 if ($chart == 'barChart') {
488 $ySize = CRM_Utils_Array::value('ySize', $params, 250);
489 $xSize = 60 * count($params['values']);
490 //hack to show tooltip.
491 if ($xSize < 200) {
492 $xSize = (count($params['values']) > 1) ? 100 * count($params['values']) : 170;
493 }
494 elseif ($xSize > 600 && count($params['values']) > 1) {
495 $xSize = (count($params['values']) + 400 / count($params['values'])) * count($params['values']);
496 }
497 }
498
499 // generate unique id for this chart instance
500 $uniqueId = md5(uniqid(rand(), TRUE));
501
502 $openFlashChart["chart_{$uniqueId}"]['size'] = array('xSize' => $xSize, 'ySize' => $ySize);
503 $openFlashChart["chart_{$uniqueId}"]['object'] = $chartObj;
504
505 // assign chart data to template
506 $template = CRM_Core_Smarty::singleton();
507 $template->assign('uniqueId', $uniqueId);
508 $template->assign("openFlashChartData", json_encode($openFlashChart));
509 }
510 }
511
512 return $openFlashChart;
513 }
514 }
515