GoogleCharts   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 59
c 0
b 0
f 0
dl 0
loc 183
rs 10
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A extEncode() 0 17 4
A encodedata() 0 7 2
A __construct() 0 4 1
A encodeaxis() 0 3 1
A showPie() 0 16 1
A show() 0 29 3
A roof() 0 25 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\statistics\Graph;
6
7
/**
8
 * \SimpleSAML\Module\statistics\Graph\GoogleCharts will help you to create a Google Chart
9
 * using the Google Charts API.
10
 *
11
 * @package SimpleSAMLphp
12
 */
13
class GoogleCharts
14
{
15
    /** @var integer */
16
    private int $x;
17
18
    /** @var integer */
19
    private int $y;
20
21
22
    /**
23
     * Constructor.
24
     *
25
     * Takes dimension of graph as parameters. X and Y.
26
     *
27
     * @param integer $x    X dimension. Default 800.
28
     * @param integer $y    Y dimension. Default 350.
29
     */
30
    public function __construct(int $x = 800, int $y = 350)
31
    {
32
        $this->x = $x;
33
        $this->y = $y;
34
    }
35
36
37
    /**
38
     * @param array $axis
39
     * @return string
40
     */
41
    private function encodeaxis(array $axis): string
42
    {
43
        return join('|', $axis);
44
    }
45
46
    /**
47
     * t:10.0,58.0,95.0
48
     * @param array $datasets
49
     * @return string
50
     */
51
    private function encodedata(array $datasets): string
52
    {
53
        $setstr = [];
54
        foreach ($datasets as $dataset) {
55
            $setstr[] = self::extEncode($dataset);
56
        }
57
        return 'e:' . join(',', $setstr);
58
    }
59
60
61
    /**
62
     * @param array $values
63
     * @return string
64
     */
65
    public static function extEncode(array $values): string // $max = 4095, $min = 0
66
    {
67
        $extended_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
68
        $chardata = '';
69
        $delta = 4095;
70
        $size = strlen($extended_table);
71
72
        foreach ($values as $k => $v) {
73
            if ($v >= 0 && $v <= 100) {
74
                $first = substr($extended_table, intval(($delta * $v / 100) / $size), 1);
75
                $second = substr($extended_table, intval(($delta * $v / 100) % $size), 1);
76
                $chardata .= "$first$second";
77
            } else {
78
                $chardata .= '__'; // Value out of max range;
79
            }
80
        }
81
        return $chardata;
82
    }
83
84
85
    /**
86
     * Generate a Google Charts URL which points to a generated image.
87
     * More documentation on Google Charts here:
88
     *   http://code.google.com/apis/chart/
89
     *
90
     * @param array $axis        Axis
91
     * @param array $axispos     Axis positions
92
     * @param array $datasets    Datasets values
93
     * @param array $maxes       Max value. Will be the topmost value on the Y-axis.
94
     * @return string
95
     */
96
    public function show(array $axis, array $axispos, array $datasets, array $maxes): string
97
    {
98
        $labeld = '&chxt=x,y' . '&chxr=0,0,1|1,0,' . $maxes[0];
99
        if (count($datasets) > 1) {
100
            if (count($datasets) !== count($maxes)) {
101
                throw new \Exception('Incorrect number of max calculations for graph plotting.');
102
            }
103
            $labeld = '&chxt=x,y,r' . '&chxr=0,0,1|1,0,' . $maxes[0] . '|2,0,' . $maxes[1];
104
        }
105
106
        $url = 'https://chart.apis.google.com/chart?' .
107
            // Dimension of graph. Default is 800x350
108
            'chs=' . $this->x . 'x' . $this->y .
109
110
            // Dateset values
111
            '&chd=' . $this->encodedata($datasets) .
112
113
            // Fill area...
114
            '&chco=ff5c00,cca600' .
115
            '&chls=1,1,0|1,6,3' .
116
117
            // chart type is linechart
118
            '&cht=lc' .
119
            $labeld .
120
            '&chxl=0:|' . $this->encodeaxis($axis) . #.$'|1:||top' .
121
            '&chxp=0,' . join(',', $axispos) .
122
            '&chg=' . (2400 / (count($datasets[0]) - 1)) . ',-1,3,3'; // lines
123
124
        return $url;
125
    }
126
127
128
    /**
129
     * @param array $axis
130
     * @param array $datasets
131
     * @return string
132
     */
133
    public function showPie(array $axis, array $datasets): string
134
    {
135
        $url = 'https://chart.apis.google.com/chart?' .
136
137
        // Dimension of graph. Default is 800x350
138
        'chs=' . $this->x . 'x' . $this->y .
139
140
        // Dateset values.
141
        '&chd=' . $this->encodedata([$datasets]) .
142
143
        // chart type is linechart
144
        '&cht=p' .
145
146
        '&chl=' . $this->encodeaxis($axis);
147
148
        return $url;
149
    }
150
151
152
    /**
153
     * Takes a input value, and generates a value that suits better as a max
154
     * value on the Y-axis. In example 37.6 will not make a good max value, instead
155
     * it will return 40. It will always return an equal or larger number than it gets
156
     * as input.
157
     *
158
     * Here is some test code:
159
     * <code>
160
     *      $foo = array(
161
     *          0, 2, 2.3, 2.6, 6, 10, 15, 98, 198, 256, 487, 563, 763, 801, 899, 999, 987, 198234.485, 283746
162
     *      );
163
     *      foreach ($foo as $f) {
164
     *          echo '<p>'.$f.' => '.\SimpleSAML\Module\statistics\Graph\GoogleCharts::roof($f);
165
     *      }
166
     * </code>
167
     *
168
     * @param int $max    Input value.
169
     * @return int
170
     */
171
    public static function roof(int $max): int
172
    {
173
        $mul = 1;
174
175
        if ($max < 1) {
176
            return 1;
177
        }
178
179
        $t = intval(ceil($max));
180
        while ($t > 100) {
181
            $t /= 10;
182
            $mul *= 10;
183
        }
184
185
        $maxGridLines = 10;
186
        $candidates = [1, 2, 5, 10, 20, 25, 50, 100];
187
188
        foreach ($candidates as $c) {
189
            if ($t / $c < $maxGridLines) {
190
                $tick_y = $c * $mul;
191
                $target_top = intval(ceil($max / $tick_y) * $tick_y);
192
                return $target_top;
193
            }
194
        }
195
        return 1;
196
    }
197
}
198