Passed
Push — scrutinizer-code-quality ( 09f5a1...c4c5fb )
by Adam
56:05 queued 14:08
created

AOR_Chart::AOR_Chart()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 2
eloc 7
c 1
b 1
f 1
nc 2
nop 0
dl 0
loc 10
ccs 0
cts 1
cp 0
crap 6
rs 9.4285
1
<?php
2
/**
3
 * Advanced OpenReports, SugarCRM Reporting.
4
 * @package Advanced OpenReports for SugarCRM
5
 * @copyright SalesAgility Ltd http://www.salesagility.com
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
18
 * along with this program; if not, see http://www.gnu.org/licenses
19
 * or write to the Free Software Foundation,Inc., 51 Franklin Street,
20
 * Fifth Floor, Boston, MA 02110-1301  USA
21
 *
22
 * @author SalesAgility <[email protected]>
23
 */
24
25
class AOR_Chart extends Basic {
26
27
    var $colours = "['#1f78b4','#a6cee3','#b2df8a','#33a02c','#fb9a99','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a','#ffff99','#b15928','#144c73','#6caed1','#8acf4e','#20641c','#f8514f','#9e1214','#fc9d24','#b35900','#a880bb','#442763','#ffff4d','#733a1a']";
28
	var $new_schema = true;
29
	var $module_dir = 'AOR_Charts';
30
	var $object_name = 'AOR_Chart';
31
	var $table_name = 'aor_charts';
32
	var $importable = true;
33
	var $disable_row_level_security = true ;
34
35
	var $id;
36
	var $name;
37
	var $date_entered;
38
	var $date_modified;
39
	var $modified_user_id;
40
	var $modified_by_name;
41
	var $created_by;
42
	var $created_by_name;
43
	var $description;
44
	var $deleted;
45
	var $created_by_link;
46
	var $modified_user_link;
47
48
    var $type;
49
    var $x_field;
50
    var $y_field;
51
    var $noDataMessage = "No Results";
52
53
54
55 7
	public function __construct(){
56 7
		parent::__construct();
57 7
	}
58
59
    /**
60
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
61
     */
62
    public function AOR_Chart(){
63
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
64
        if(isset($GLOBALS['log'])) {
65
            $GLOBALS['log']->deprecated($deprecatedMessage);
66
        }
67
        else {
68
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
69
        }
70
        self::__construct();
71
    }
72
73
74 1
    function save_lines(array $post,AOR_Report $bean,$postKey){
75 1
        $seenIds = array();
76 1
        if(isset($post[$postKey.'id'])) {
77 1
            foreach ($post[$postKey . 'id'] as $key => $id) {
78 1
                if ($id) {
79
                    $aorChart = BeanFactory::getBean('AOR_Charts', $id);
80
                } else {
81 1
                    $aorChart = BeanFactory::newBean('AOR_Charts');
82
                }
83 1
                $aorChart->name = $post[$postKey . 'title'][$key];
84 1
                $aorChart->type = $post[$postKey . 'type'][$key];
85 1
                $aorChart->x_field = $post[$postKey . 'x_field'][$key];
86 1
                $aorChart->y_field = $post[$postKey . 'y_field'][$key];
87 1
                $aorChart->aor_report_id = $bean->id;
88 1
                $aorChart->save();
89 1
                $seenIds[] = $aorChart->id;
90
            }
91
        }
92
        //Any beans that exist but aren't in $seenIds must have been removed.
93 1
        foreach($bean->get_linked_beans('aor_charts','AOR_Charts') as $chart){
94 1
            if(!in_array($chart->id,$seenIds)){
95 1
                $chart->mark_deleted($chart->id);
96
            }
97
        }
98 1
    }
99
100 1
    private function getValidChartTypes(){
101 1
        return array('bar','line','pie','radar','rose', 'grouped_bar', 'stacked_bar');
102
    }
103
104
105
    private function getColour($seed,$rgbArray = false){
106
        $hash = md5($seed);
107
        $r = hexdec(substr($hash, 0, 2));
108
        $g = hexdec(substr($hash, 2, 2));
109
        $b = hexdec(substr($hash, 4, 2));
110
        if($rgbArray){
111
            return array('R'=>$r,'G'=>$g,'B'=>$b);
112
        }
113
        $highR = $r + 10;
114
        $highG = $g + 10;
115
        $highB = $b + 10;
116
        $main = '#'.str_pad(dechex($r),2,'0',STR_PAD_LEFT)
117
            .str_pad(dechex($g),2,'0',STR_PAD_LEFT)
118
            .str_pad(dechex($b),2,'0',STR_PAD_LEFT);
119
        $highlight = '#'.dechex($highR).dechex($highG).dechex($highB);
120
        return array('main'=>$main,'highlight'=>$highlight);
121
    }
122
123
    function buildChartImageBar($chartPicture,$recordImageMap = false){
124
        $scaleSettings = array("DrawSubTicks" => false, "LabelRotation" => 30, 'MinDivHeight' => 50);
125
        $chartPicture->drawScale($scaleSettings);
126
        $chartPicture->drawBarChart(array("RecordImageMap"=>$recordImageMap));
127
    }
128
129
    function buildChartImagePie($chartPicture,$chartData, $reportData,$imageHeight, $imageWidth, $xName,$recordImageMap){
130
        $PieChart = new pPie($chartPicture,$chartData);
131
        $x = 0;
132
        foreach($reportData as $row){
133
            $PieChart->setSliceColor($x,$this->getColour($row[$xName],true));
134
            $x++;
135
        }
136
        $PieChart->draw2DPie($imageWidth/3,$imageHeight/2,array("Border"=>TRUE,'Radius'=>200,''=>true,"RecordImageMap"=>$recordImageMap));
137
        $PieChart->drawPieLegend($imageWidth*0.7,$imageHeight/3, array('FontSize'=>10,"FontName"=>"modules/AOR_Charts/lib/pChart/fonts/verdana.ttf",'BoxSize'=>14));
138
    }
139
140
    function buildChartImageLine($chartPicture, $recordImageMap = false){
141
        $scaleSettings = array("XMargin"=>10,"YMargin"=>10,"GridR"=>200,"GridG"=>200,"GridB"=>200,'MinDivHeight' => 50,"LabelRotation" => 30);
142
        $chartPicture->drawScale($scaleSettings);
143
        $chartPicture->drawLineChart(array("RecordImageMap"=>$recordImageMap));
144
    }
145
146
    function buildChartImageRadar($chartPicture, $chartData,$recordImageMap){
147
        $SplitChart = new pRadar();
148
        $Options = array("LabelPos"=>RADAR_LABELS_HORIZONTAL,"RecordImageMap"=>$recordImageMap);
149
        $SplitChart->drawRadar($chartPicture,$chartData,$Options);
150
151
    }
152
153 1
    public function buildChartImage(array $reportData, array $fields,$asDataURI = true, $generateImageMapId = false){
154 1
        global $current_user;
155 1
        require_once 'modules/AOR_Charts/lib/pChart/pChart.php';
156
157 1
        if($generateImageMapId !== false){
158 1
            $generateImageMapId = $current_user->id."-".$generateImageMapId;
159
        }
160
161 1
        $html = '';
162 1
        if(!in_array($this->type, $this->getValidChartTypes())){
163
            return $html;
164
        }
165 1
        $x = $fields[$this->x_field];
166 1
        $y = $fields[$this->y_field];
167 1
        if(!$x || !$y){
168
            //Malformed chart object - missing an axis field
169 1
            return '';
170
        }
171
        $xName = str_replace(' ','_',$x->label) . $this->x_field;
172
        $yName = str_replace(' ','_',$y->label) . $this->y_field;
173
174
        $chartData = new pData();
175
        $chartData->loadPalette("modules/AOR_Charts/lib/pChart/palettes/navy.color", TRUE);
176
        $labels = array();
177
        foreach($reportData as $row){
178
            $chartData->addPoints($row[$yName],'data');
179
            $chartData->addPoints($row[$xName],'Labels');
180
            $labels[] = $row[$xName];
181
        }
182
183
        $chartData->setSerieDescription("Months","Month");
184
        $chartData->setAbscissa("Labels");
185
186
        $imageHeight = 700;
187
        $imageWidth = 700;
188
189
        $chartPicture = new pImage($imageWidth,$imageHeight,$chartData);
190
        if($generateImageMapId){
191
            $imageMapDir = create_cache_directory('modules/AOR_Charts/ImageMap/'.$current_user->id.'/');
192
            $chartPicture->initialiseImageMap($generateImageMapId,IMAGE_MAP_STORAGE_FILE,$generateImageMapId,$imageMapDir);
193
        }
194
195
        $chartPicture->Antialias = True;
196
197
        $chartPicture->drawFilledRectangle(0,0,$imageWidth-1,$imageHeight-1,array("R"=>240,"G"=>240,"B"=>240,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0,));
198
199
        $chartPicture->setFontProperties(array("FontName"=>"modules/AOR_Charts/lib/pChart/fonts/verdana.ttf","FontSize"=>14));
200
201
        $chartPicture->drawText($imageWidth/2,20,$this->name,array("R"=>0,"G"=>0,"B"=>0,'Align'=>TEXT_ALIGN_TOPMIDDLE));
202
        $chartPicture->setFontProperties(array("FontName"=>"modules/AOR_Charts/lib/pChart/fonts/verdana.ttf","FontSize"=>6));
203
204
        $chartPicture->setGraphArea(60,60,$imageWidth-60,$imageHeight-100);
205
206
        switch($this->type){
207
            case 'radar':
208
                $this->buildChartImageRadar($chartPicture, $chartData, !empty($generateImageMapId));
209
                break;
210
            case 'pie':
211
                $this->buildChartImagePie($chartPicture,$chartData, $reportData,$imageHeight, $imageWidth, $xName, !empty($generateImageMapId));
212
                break;
213
            case 'line':
214
                $this->buildChartImageLine($chartPicture, !empty($generateImageMapId));
215
                break;
216
            case 'bar':
217
            default:
218
                $this->buildChartImageBar($chartPicture, !empty($generateImageMapId));
219
                break;
220
        }
221
        if($generateImageMapId) {
222
            $chartPicture->replaceImageMapTitle("data", $labels);
223
        }
224
        ob_start();
225
        $chartPicture->render('');
226
        $img = ob_get_clean();
227
        if($asDataURI){
228
            return 'data:image/png;base64,'.base64_encode($img);
229
        }else{
230
            return $img;
231
        }
232
    }
233
234 1
    public function buildChartHTML(array $reportData, array $fields,$index = 0, $chartType = AOR_Report::CHART_TYPE_PCHART, AOR_Field $mainGroupField = null){
235
        switch($chartType){
236 1
            case AOR_Report::CHART_TYPE_PCHART:
237 1
                return $this->buildChartHTMLPChart($reportData,$fields,$index);
238
            case AOR_Report::CHART_TYPE_CHARTJS:
239
                return $this->buildChartHTMLChartJS($reportData,$fields);
240
            case AOR_Report::CHART_TYPE_RGRAPH:
241
                return $this->buildChartHTMLRGraph($reportData,$fields, $mainGroupField);
242
        }
243
        return '';
244
    }
245
246
247
    private function buildChartHTMLRGraph(array $reportData, array $fields, AOR_Field $mainGroupField = null){
248
        $html = '';
249
        if(!in_array($this->type, $this->getValidChartTypes())){
250
            return $html;
251
        }
252
        $x = $fields[$this->x_field];
253
        $y = $fields[$this->y_field];
254
        if(!$x || !$y){
255
            //Malformed chart object - missing an axis field
256
            return '';
257
        }
258
        $xName = str_replace(' ','_',$x->label) . $this->x_field;
259
        $yName = str_replace(' ','_',$y->label) . $this->y_field;
260
261
        $defaultHeight = 500;
262
        $defaultWidth = 900;
263
264
        switch($this->type){
265
            /*
266
             //Polar was not implemented for the previous library (it is not in the getValidChartTypes method)
267
            case 'polar':
268
                $chartFunction = 'PolarArea';
269
                $data = $this->getPolarChartData($reportData, $xName,$yName);
270
                $config = $this->getPolarChartConfig();
271
                break;
272
            */
273
            case 'radar':
274
                $chartFunction = 'Radar';
275
                $data = $this->getRGraphBarChartData($reportData, $xName,$yName);
276
                $config = $this->getRadarChartConfig();
277
                $chart = $this->getRGraphRadarChart(json_encode($data['data']), json_encode($data['labels']),json_encode($data['tooltips']), $this->name, $this->id, $defaultHeight,$defaultWidth);
278
                break;
279
            case 'pie':
280
                $chartFunction = 'Pie';
281
                $data = $this->getRGraphBarChartData($reportData, $xName,$yName);
282
                $config = $this->getPieChartConfig();
283
                $chart = $this->getRGraphPieChart(json_encode($data['data']), json_encode($data['labels']),json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth);
284
                break;
285
            case 'line':
286
                $chartFunction = 'Line';
287
                $data = $this->getRGraphBarChartData($reportData, $xName,$yName);
288
                $config = $this->getLineChartConfig();
289
                $chart = $this->getRGraphLineChart(json_encode($data['data']), json_encode($data['labels']),json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth);
290
                break;
291
            case 'rose':
292
                $chartFunction = 'Rose';
293
                $data = $this->getRGraphBarChartData($reportData, $xName,$yName);
294
                $config = $this->getRoseChartConfig();
295
                $chart = $this->getRGraphRoseChart(json_encode($data['data']), json_encode($data['labels']),json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth);
296
                break;
297
            case 'grouped_bar':
298
                $chartFunction = 'Grouped bar';
299
                $data = $this->getRGraphGroupedBarChartData($reportData, $xName,$yName, $mainGroupField);
300
                $config = $this->getGroupedBarChartConfig();
301
                $chart = $this->getRGraphGroupedBarChart(json_encode($data['data']), json_encode($data['labels']), json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth, true);
302
                break;
303
            case 'stacked_bar':
304
                $chartFunction = 'Stacked bar';
305
                $data = $this->getRGraphGroupedBarChartData($reportData, $xName,$yName, $mainGroupField);
306
                $config = $this->getStackedBarChartConfig();
307
                $chart = $this->getRGraphGroupedBarChart(json_encode($data['data']), json_encode($data['labels']), json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth, false);
308
                break;
309
            case 'bar':
310
            default:
311
                $chartFunction = 'Bar';
312
                $data = $this->getRGraphBarChartData($reportData, $xName,$yName);
313
                $config = $this->getBarChartConfig();
314
                $chart = $this->getRGraphBarChart(json_encode($data['data']), json_encode($data['labels']), json_encode($data['tooltips']), $this->name, $this->id,  $defaultHeight,$defaultWidth);
315
                break;
316
        }
317
318
        return $chart;
319
    }
320
321
    private function getRGraphRoseChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400)
322
    {
323
        $dataArray = json_decode($chartDataValues);
324
        if(!is_array($dataArray)||count($dataArray) < 1)
325
        {
326
            return "<h3>$this->noDataMessage</h3>";
327
        }
328
        $html = '';
329
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
330
        $html .= <<<EOF
331
        <script>
332
            new RGraph.Rose({
333
            id: '$chartId',
334
            options:{
335
                //title: '$chartName',
336
                //labels: $chartLabelValues,
337
                //textSize:8,
338
                textSize:10,
339
                //titleSize:10,
340
                 tooltips:$chartTooltips,
341
                tooltipsEvent:'onmousemove',
342
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
343
                colors: $this->colours,
344
                colorsSequential:true
345
            },
346
            data: $chartDataValues
347
        }).draw();
348
        </script>
349
EOF;
350
        return $html;
351
    }
352
353
354
355
    //I have not used a parameter for getRGraphBarChart to say whether to group etc, as the future development could be quite different
356
    //for both, hence the separate methods.  However, the $grouped parameter allows us to specify whether the chart is grouped (true)
357
    //or stacked (false)
358
    private function getRGraphGroupedBarChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400, $grouped = false)
359
    {
360
        $dataArray = json_decode($chartDataValues);
361
        $grouping = 'grouped'; //$mainGroupField->label; //'grouped';
362
        if(!$grouped)
363
            $grouping='stacked';
364
        if(!is_array($dataArray)||count($dataArray) < 1)
365
        {
366
            return "<h3>$this->noDataMessage</h3>";
367
        }
368
        $html = '';
369
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
370
        $html .= <<<EOF
371
        <script>
372
            new RGraph.Bar({
373
            id: '$chartId',
374
            data: $chartDataValues,
375
            options: {
376
                grouping:'$grouping',
377
                backgroundGrid:false,
378
                backgroundGrid:false,
379
                gutterBottom: 150,
380
                //gutterTop:40,
381
                //gutterLeft:30,
382
                title: '$chartName',
383
384
                tooltips:$chartTooltips,
385
                tooltipsEvent:'onmousemove',
386
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
387
388
                gutterLeft:50,
389
                shadow:false,
390
                titleSize:10,
391
                labels: $chartLabelValues,
392
                textSize:10,
393
                textAngle: 90,
394
                colors: $this->colours,
395
                ymax:calculateMaxYForSmallNumbers($chartDataValues)
396
            }
397
        }).draw();
398
        </script>
399
EOF;
400
        return $html;
401
    }
402
403
404
405
    private function getRGraphBarChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400)
406
    {
407
        $dataArray = json_decode($chartDataValues);
408
        if(!is_array($dataArray)||count($dataArray) < 1)
409
        {
410
            return "<h3>$this->noDataMessage</h3>";
411
        }
412
        $html = '';
413
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
414
        $html .= <<<EOF
415
        <script>
416
            new RGraph.Bar({
417
            id: '$chartId',
418
            data: $chartDataValues,
419
            options: {
420
            title: '$chartName',
421
                gutterBottom: 150,
422
                gutterLeft:50,
423
                //gutterTop:50,
424
                //title: '$chartName',
425
                labels: $chartLabelValues,
426
                colorsSequential:true,
427
                textAngle: 90,
428
                textSize:10,
429
                titleSize:10,
430
                backgroundGrid:false,
431
432
                tooltips:$chartTooltips,
433
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
434
                tooltipsEvent:'onmousemove',
435
436
                colors: $this->colours,
437
                ymax:calculateMaxYForSmallNumbers($chartDataValues)
438
            }
439
        }).draw();
440
        </script>
441
EOF;
442
        return $html;
443
    }
444
445
    private function getRGraphRadarChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400)
446
    {
447
        $dataArray = json_decode($chartDataValues);
448
        if(!is_array($dataArray)||count($dataArray) < 1)
449
        {
450
            return "<h3>$this->noDataMessage</h3>";
451
        }
452
        $html = '';
453
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
454
        $html .= <<<EOF
455
        <script>
456
            new RGraph.Radar({
457
            id: '$chartId',
458
            data: $chartDataValues,
459
            options: {
460
                title: '$chartName',
461
                labels: $chartLabelValues,
462
                textSize:10,
463
464
465
                tooltips:$chartTooltips,
466
                tooltipsEvent:'onmousemove',
467
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
468
469
                colors: $this->colours,
470
                ymax:calculateMaxYForSmallNumbers($chartDataValues)
471
            }
472
        }).draw();
473
        </script>
474
EOF;
475
        return $html;
476
    }
477
478
    private function getRGraphPieChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400)
479
    {
480
        $dataArray = json_decode($chartDataValues);
481
        if(!is_array($dataArray)||count($dataArray) < 1)
482
        {
483
            return "<h3>$this->noDataMessage</h3>";
484
        }
485
/*
486
        if($chartHeight > 400)
487
            $chartHeight = 400;
488
        if($chartWidth > 600)
489
            $chartWidth = 400;
490
*/
491
        $html = '';
492
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
493
        $html .= <<<EOF
494
        <script>
495
            new RGraph.Pie({
496
            id: '$chartId',
497
            data: $chartDataValues,
498
            options: {
499
                title: '$chartName',
500
                textSize:10,
501
                titleSize:10,
502
                 tooltips:$chartTooltips,
503
                tooltipsEvent:'onmousemove',
504
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
505
                labels: $chartLabelValues,
506
                colors: $this->colours
507
            }
508
        }).draw();
509
        </script>
510
EOF;
511
        return $html;
512
    }
513
514
    private function getRGraphLineChart($chartDataValues, $chartLabelValues,$chartTooltips, $chartName, $chartId, $chartHeight = 400, $chartWidth = 400)
515
    {
516
        $dataArray = json_decode($chartDataValues);
517
        if(!is_array($dataArray)||count($dataArray) < 1)
518
        {
519
            return "<h3>$this->noDataMessage</h3>";
520
        }
521
        $html = '';
522
        $html .= "<canvas id='$chartId' width='$chartWidth' height='$chartHeight' class='resizableCanvas'></canvas>";
523
        $html .= <<<EOF
524
        <script>
525
            new RGraph.Line({
526
            id: '$chartId',
527
            data: $chartDataValues,
528
            options: {
529
                title: '$chartName',
530
                gutterBottom: 150,
531
                //gutterTop:50,
532
                tickmarks:'encircle',
533
                textSize:10,
534
                titleSize:10,
535
                gutterLeft:70,
536
                //title: '$chartName',
537
                labels: $chartLabelValues,
538
539
                 tooltips:$chartTooltips,
540
                tooltipsEvent:'onmousemove',
541
                tooltipsCssClass: 'rgraph_chart_tooltips_css',
542
543
                tickmarks:'circle',
544
545
                textAngle: 90,
546
                //titleSize:10,
547
                backgroundGrid:false,
548
                colors: $this->colours,
549
                ymax:calculateMaxYForSmallNumbers($chartDataValues),
550
            }
551
        }).draw();
552
        </script>
553
EOF;
554
        return $html;
555
    }
556
557
    private function buildChartHTMLChartJS(array $reportData, array $fields){
558
        $html = '';
559
        if(!in_array($this->type, $this->getValidChartTypes())){
560
            return $html;
561
        }
562
        $x = $fields[$this->x_field];
563
        $y = $fields[$this->y_field];
564
        if(!$x || !$y){
565
            //Malformed chart object - missing an axis field
566
            return '';
567
        }
568
        $xName = str_replace(' ','_',$x->label) . $this->x_field;
569
        $yName = str_replace(' ','_',$y->label) . $this->y_field;
570
571
        switch($this->type){
572
            case 'polar':
573
                $chartFunction = 'PolarArea';
574
                $data = $this->getPolarChartData($reportData, $xName,$yName);
575
                $config = $this->getPolarChartConfig();
576
                break;
577
            case 'radar':
578
                $chartFunction = 'Radar';
579
                $data = $this->getRadarChartData($reportData, $xName,$yName);
580
                $config = $this->getRadarChartConfig();
581
                break;
582
            case 'pie':
583
                $chartFunction = 'Pie';
584
                $data = $this->getPieChartData($reportData, $xName,$yName);
585
                $config = $this->getPieChartConfig();
586
                break;
587
            case 'line':
588
                $chartFunction = 'Line';
589
                $data = $this->getLineChartData($reportData, $xName,$yName);
590
                $config = $this->getLineChartConfig();
591
                break;
592
            case 'bar':
593
            default:
594
                $chartFunction = 'Bar';
595
                $data = $this->getBarChartData($reportData, $xName,$yName);
596
                $config = $this->getBarChartConfig();
597
                break;
598
        }
599
        $data = json_encode($data);
600
        $config = json_encode($config);
601
        $chartId = 'chart'.$this->id;
602
        $html .= "<h3>{$this->name}</h3>";
603
        $html .= "<canvas id='{$chartId}' width='400' height='400'></canvas>";
604
        $html .= <<<EOF
605
        <script>
606
        $(document).ready(function(){
607
            SUGAR.util.doWhen("typeof Chart != 'undefined'", function(){
608
                var data = {$data};
609
                var ctx = document.getElementById("{$chartId}").getContext("2d");
610
                console.log('Creating new chart');
611
                var config = {$config};
612
                var chart = new Chart(ctx).{$chartFunction}(data, config);
613
                var legend = chart.generateLegend();
614
                $('#{$chartId}').after(legend);
615
            });
616
        });
617
        </script>
618
EOF;
619
        return $html;
620
    }
621
622 1
    private function buildChartHTMLPChart(array $reportData, array $fields,$index = 0){
623 1
        $html = '';
624 1
        $imgUri = $this->buildChartImage($reportData,$fields,true,$index);
625 1
        $img = "<img id='{$this->id}_img' src='{$imgUri}'>";
626 1
        $html .= $img;
627
        $html .= <<<EOF
628
<script>
629
SUGAR.util.doWhen("typeof addImage != 'undefined'", function(){
630 1
    addImage('{$this->id}_img','{$this->id}_img_map','index.php?module=AOR_Charts&action=getImageMap&to_pdf=1&imageMapId={$index}');
631
});
632 1
</script>
633
EOF;
634 1
        return $html;
635
    }
636
637
    private function getShortenedLabel($label, $maxLabelSize = 20)
638
    {
639
        if(strlen($label) > $maxLabelSize)
640
        {
641
            return substr($label,0,$maxLabelSize).'...';
642
        }
643
        else
644
            return $label;
645
    }
646
647
648
    private function getRGraphGroupedBarChartData($reportData, $xName,$yName, AOR_Field $mainGroupField = null){
649
650
651
        // get z-axis name
652
653
        $zName = null;
654
        foreach($reportData[0] as $key => $value) {
655
            $field = str_replace(' ', '_', is_null($mainGroupField) ? 'no data' : $mainGroupField->label);
656
            if (preg_match('/^' . $field . '[0-9]+/', $key)) {
657
                $zName = $key;
658
                break;
659
            }
660
        }
661
662
663
664
        // get grouped values
665
666
        $data = array();
667
        $tooltips = array();
668
669
        $usedKeys = array();
670
        foreach($reportData as $key => $row) {
671
            $filter = $row[$xName];
672
            foreach($reportData as $key2 => $row2) {
673
                if($row2[$xName] == $filter && !in_array($key, $usedKeys)) {
674
                    $data      [ $row[$xName]  ]   [] = (float) $row[$yName];
675
                    $tooltips  [ $row[$xName]  ]   [] = isset($row[$zName]) ? $row[$zName] : null;
676
                    $usedKeys[] = $key;
677
                }
678
            }
679
        }
680
681
        $_data = array();
682
        foreach($data as $label => $values) {
683
            foreach($values as $key => $value) {
684
                $_data[$label][$tooltips[$label][$key]] = $value;
685
            }
686
        }
687
        $data = $_data;
688
689
690
        // make data format for charts
691
692
        $_data = array();
693
        $_labels = array();
694
        $_tooltips = array();
695
        foreach($data as $label => $values) {
696
            $_labels[] = $this->getShortenedLabel($label);
697
            $_values = array();
698
            foreach($values as $tooltip => $value) {
699
                $_tooltips[] = $tooltip . " ($value)";
700
                $_values[] = $value;
701
            }
702
            $_data[] = $_values;
703
        }
704
705
706
        $chart = array(
707
            'data' => $_data,
708
            'labels' => $_labels,
709
            'tooltips' => $_tooltips,
710
        );
711
712
        return $chart;
713
714
715
    }
716
717
    private function getRGraphBarChartData($reportData, $xName,$yName){
718
        $chart['labels']=array();
719
        $chart['data']=array();
720
        $chart['tooltips']=array();
721
        foreach($reportData as $row){
722
            $chart['labels'][] = $this->getShortenedLabel($row[$xName]);
723
            $chart['tooltips'][] = $row[$xName];
724
            $chart['data'][] = (float)$row[$yName];
725
726
        }
727
        return $chart;
728
    }
729
730
731
    private function getBarChartData($reportData, $xName,$yName){
732
        $data = array();
733
        $data['labels'] = array();
734
        $datasetData = array();
735
        foreach($reportData as $row){
736
            $data['labels'][] = $row[$xName];
737
            $datasetData[] = $row[$yName];
738
        }
739
740
        $data['datasets'] = array();
741
        $data['datasets'][] = array(
742
            'fillColor' => "rgba(151,187,205,0.2)",
743
            'strokeColor' => "rgba(151,187,205,1)",
744
            'pointColor' => "rgba(151,187,205,1)",
745
            'pointStrokeColor' => "#fff",
746
            'pointHighlightFill' => "#fff",
747
            'pointHighlightStroke' => "rgba(151,187,205,1)4",
748
            'data'=>$datasetData);
749
        return $data;
750
    }
751
752
    private function getLineChartData($reportData, $xName,$yName){
753
        return $this->getBarChartData($reportData, $xName,$yName);
754
    }
755
756
    private function getBarChartConfig(){
757
        return array();
758
    }
759
    private function getLineChartConfig(){
760
        return $this->getBarChartConfig();
761
    }
762
763
    private function getGroupedBarChartConfig()
764
    {
765
        return $this->getBarChartConfig();
766
    }
767
768
    private function getStackedBarChartConfig()
769
    {
770
        return $this->getBarChartConfig();
771
    }
772
773
    private function getRoseChartConfig(){
774
        return $this->getBarChartConfig();
775
    }
776
777
    private function getRadarChartData($reportData, $xName,$yName){
778
        return $this->getBarChartData($reportData, $xName,$yName);
779
    }
780
781
    private function getPolarChartData($reportData, $xName,$yName){
782
        return $this->getPieChartData($reportData, $xName,$yName);
783
    }
784
785
    private function getRadarChartConfig(){
786
        return array();
787
    }
788
789
    private function getPolarChartConfig(){
790
        return $this->getPieChartConfig();
791
    }
792
    private function getPieChartConfig(){
793
        $config = array();
794
        $config['legendTemplate'] = "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\">&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;<%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>";
795
        return $config;
796
    }
797
798
    private function getPieChartData($reportData, $xName,$yName){
799
        $data = array();
800
801
        foreach($reportData as $row){
802
            if(!$row[$yName]){
803
                continue;
804
            }
805
            $colour = $this->getColour($row[$xName]);
806
            $data[] = array(
807
                'value' => (int)$row[$yName],
808
                'label' => $row[$xName],
809
                'color' => $colour['main'],
810
                'highlight' => $colour['highlight'],
811
            );
812
        }
813
        return $data;
814
    }
815
816
817
}
818