GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

SeriesDataHelper   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 21
lcom 1
cbo 5
dl 0
loc 189
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A setData() 0 13 3
A setColumns() 0 8 3
A jsonSerialize() 0 4 1
B process() 0 28 5
C normalizeColumns() 0 30 7
A getFormatters() 0 11 1
1
<?php
2
3
/**
4
 * SeriesDataHelper class file.
5
 *
6
 * @author Milo Schuman <[email protected]>
7
 * @link https://github.com/miloschuman/yii2-highcharts/
8
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
9
 */
10
11
namespace miloschuman\highcharts;
12
13
use JsonSerializable;
14
use yii\base\Component;
15
use yii\base\InvalidConfigException;
16
use yii\base\InvalidParamException;
17
use yii\data\ArrayDataProvider;
18
use yii\data\BaseDataProvider;
19
use yii\helpers\ArrayHelper;
20
21
/**
22
 * SeriesDataHelper makes it easier to get data from your database/data provider into your chart.
23
 *
24
 * It includes a set of built-in formatters to handle common preprocessing tasks (like converting
25
 * datetime strings to JavaScript timestamps) and provides an extensible column configuration, which
26
 * allows you to add custom parser/formatter handlers.
27
 *
28
 * Basic usage:
29
 * ```php
30
 * use miloschuman\highcharts\Highstock;
31
 * use miloschuman\highcharts\SeriesDataHelper;
32
 *
33
 * Highstock::widget([
34
 *     'options' => [
35
 *         'series' => [
36
 *             [
37
 *                 'type' => 'candlestick',
38
 *                 'name' => 'Stock',
39
 *                 'data' => new SeriesDataHelper($dataProvider, ['date:datetime', 'open', 'high', 'low', 'close']),
40
 *             ],
41
 *             [
42
 *                 'type' => 'column',
43
 *                 'name' => 'Volume',
44
 *                 'data' => new SeriesDataHelper($dataProvider, ['date:datetime', 'volume:int']),
45
 *             ],
46
 *         ]
47
 *     ]
48
 * ]);
49
 * ```
50
 *
51
 * @property-write BaseDataProvider|array $data
52
 * @property-write array $columns
53
 */
54
class SeriesDataHelper extends Component implements JsonSerializable
55
{
56
57
    /**
58
     * @var array column configuration
59
     */
60
    protected $columns;
61
62
    /**
63
     * @var BaseDataProvider|array the underlying data source
64
     */
65
    protected $data;
66
67
68
    /**
69
     * Constructor
70
     * 
71
     * @param BaseDataProvider|array $data the underlying data source
72
     * @param array $columns column configuration
73
     * @param array $config for future use
74
     * @see setColumns()
75
     * @see setData()
76
     */
77
    public function __construct($data, $columns, $config = [])
78
    {
79
        parent::__construct($config);
80
81
        $this->setData($data);
82
        $this->setColumns($columns);
83
    }
84
85
86
    /**
87
     * Sets the underlying data source.
88
     * 
89
     * @param BaseDataProvider|array $data the data source
90
     * @throws InvalidParamException
91
     */
92
    public function setData($data)
93
    {
94
        if ($data instanceof BaseDataProvider) {
95
            $this->data = $data;
96
        } elseif (is_array($data)) {
97
            $this->data = new ArrayDataProvider([
98
                'allModels' => $data,
99
                'pagination' => ['pageSize' => 0],
100
            ]);
101
        } else {
102
            throw new InvalidParamException('Data must be an array or extend BaseDataProvider');
103
        }
104
    }
105
106
107
    /**
108
     * Sets the column configuration.
109
     *
110
     * Each element can be either an array `['column', 'format']` or a shortcut string
111
     * `'column:format'`.
112
     *
113
     * Column can be a string representing the attribute, field, or key from the
114
     * source data. It can even be an integer if the source data uses numeric keys.
115
     *
116
     * Format can be one of the built-in formatters ('datetime', 'float', 'int', 'raw', 'string', or
117
     * 'timestamp') or a callable that is used to prepare each data value. If format is omitted, the
118
     * raw value will be passed to the chart.
119
     *
120
     * Example showing different ways to specify a column:
121
     *
122
     * ```php
123
     * [
124
     *     ['date_measured', 'datetime'],
125
     *     'open',
126
     *     'high:float',
127
     *     ['low', 'float'],
128
     *     ['close', function($value) {
129
     *         return ceil($value);
130
     *     }]
131
     * ]
132
     * ```
133
     *
134
     * @param array $columns
135
     * @throws InvalidParamException
136
     */
137
    public function setColumns($columns)
138
    {
139
        if (!is_array($columns) || !count($columns)) {
140
            throw new InvalidParamException('Columns must be an array with at least one element.');
141
        }
142
143
        $this->columns = $columns;
144
    }
145
146
147
    /**
148
     * @inheritdoc
149
     */
150
    public function jsonSerialize()
151
    {
152
        return $this->process();
153
    }
154
155
156
    /**
157
     * Processes the source data and returns the result.
158
     *
159
     * @return array the processed data
160
     */
161
    public function process()
162
    {
163
        if (empty($this->data)) {
164
            throw new InvalidConfigException('Missing required "data" property.');
165
        }
166
167
        $this->normalizeColumns();
168
169
        // return simple array for single-column configs
170
        if (count($this->columns) === 1) {
171
            $column = $this->columns[0];
172
            $data = ArrayHelper::getColumn($this->data->models, $column[0]);
173
            return array_map($column[1], $data);
174
        }
175
176
        // use two-dimensional array for multi-column configs
177
        $data = [];
178
        foreach ($this->data->models as $model) {
179
            $row = [];
180
            foreach ($this->columns as $index => $column) {
181
                $row[$index] = call_user_func($column[1], $model[$column[0]]);
182
            }
183
184
            $data[] = $row;
185
        }
186
187
        return $data;
188
    }
189
190
191
    /**
192
     * Prepares the [[$columns]] for use by [[process()]].
193
     */
194
    protected function normalizeColumns()
195
    {
196
        $formatters = $this->getFormatters();
197
198
        foreach ($this->columns as $index => $column) {
199
200
            // convert shorthand string and int configs to array
201
            if (is_string($column)) {
202
                $column = explode(':', $column);
203
            } elseif (is_int($column)) {
204
                $column = [$column];
205
            }
206
207
            // default to 'raw' formatter if none is specified
208
            if (!isset($column[1])) {
209
                $column[1] = 'raw';
210
            }
211
212
            // assign built-in formatters
213
            if (!is_callable($column[1])) {
214
                if (array_key_exists($column[1], $formatters)) {
215
                    $column[1] = $formatters[$column[1]];
216
                } else {
217
                    throw new InvalidConfigException("Invalid formatter for column: {$column[0]}.");
218
                }
219
            }
220
221
            $this->columns[$index] = $column;
222
        }
223
    }
224
225
226
    /**
227
     * Built-in formatters, which can be used in the [[$columns]] configuration.
228
     *
229
     * @return callable[]
230
     */
231
    protected function getFormatters()
232
    {
233
        return [
234
            'datetime' => function ($val) { return (float) strtotime($val) * 1000; },
235
            'int' => 'intval',
236
            'float' => 'floatval',
237
            'raw' => function ($val) { return $val; },
238
            'string' => 'strval',
239
            'timestamp' => function ($val) { return (float) $val * 1000; },
240
        ];
241
    }
242
}
243