This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the ReportBundle package |
||
5 | * |
||
6 | * (c) symball <http://simonball.me> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE file |
||
9 | * that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | |||
13 | namespace Symball\ReportBundle\Service; |
||
14 | |||
15 | /** |
||
16 | * The meta service acts as a data broker in which the column headings, data |
||
17 | * points and various options are handled |
||
18 | * |
||
19 | * @author Simon Ball <simonball at simonball dot me> |
||
20 | */ |
||
21 | class Meta |
||
22 | { |
||
23 | |||
24 | protected $dataPoints = array(); |
||
25 | protected $currentDataPoint; |
||
26 | protected $currentDataSet = array(); |
||
27 | protected $dataPointMeta; |
||
28 | protected $options = array( |
||
29 | 'default_bg_color' => 'e9e9e9', |
||
30 | 'default_line_thickness' => 'thick', |
||
31 | 'positive_color' => 'd8ffb7', |
||
32 | 'negative_color' => 'ffc56c', |
||
33 | ); |
||
34 | private $columnCount = 0; |
||
35 | |||
36 | /** |
||
37 | * Define an option and its value. |
||
38 | * |
||
39 | * @param string $key |
||
40 | * @param mixed $value |
||
41 | * @return $this For method chaining |
||
42 | * @throws \InvalidArgumentException if key type is not a string or integer |
||
43 | */ |
||
44 | View Code Duplication | public function setOption($key, $value) |
|
0 ignored issues
–
show
|
|||
45 | { |
||
46 | if (is_int($key) || is_string($key)) { |
||
47 | $this->options[$key] = $value; |
||
48 | } else { |
||
49 | throw new \InvalidArgumentException('Option key must be an integer or string. ' . gettype($key) . ' given'); |
||
50 | } |
||
51 | |||
52 | return $this; |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * Set a group of options at the same time |
||
57 | * |
||
58 | * @param array $options |
||
59 | * @return $this For method chaining |
||
60 | * @throws \InvalidArgumentException If input is not an array |
||
61 | */ |
||
62 | View Code Duplication | public function setOptions($options) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
63 | { |
||
64 | if (is_array($options)) { |
||
65 | $this->options = array_merge($this->options, $options); |
||
66 | } else { |
||
67 | throw new \InvalidArgumentException('Options must be an array. ' . gettype($options) . ' given'); |
||
68 | } |
||
69 | |||
70 | return $this; |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * Get the value of a single option or return false if it doesn't exist |
||
75 | * |
||
76 | * @param string|integer $key |
||
77 | * @return string|integer|boolean The option value |
||
78 | */ |
||
79 | public function getOption($key) |
||
80 | { |
||
81 | if ($key && isset($this->options[$key])) { |
||
82 | return $this->options[$key]; |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Retrieve the full option array |
||
88 | * |
||
89 | * @return array |
||
90 | */ |
||
91 | public function getOptions() |
||
92 | { |
||
93 | return $this->options; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Reset data set values for all data points back to the defaults as in the |
||
98 | * column definition |
||
99 | * |
||
100 | * @return $this For method chaining |
||
101 | */ |
||
102 | public function clear() |
||
103 | { |
||
104 | $this->currentDataSet = array(); |
||
105 | $this->currentDataSet = array_fill_keys( |
||
106 | $this->dataPoints, |
||
107 | $this->dataPointMeta |
||
108 | ); |
||
109 | |||
110 | return $this; |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * Remove reference to all existing data points |
||
115 | * |
||
116 | * @return $this For method chaining |
||
117 | */ |
||
118 | public function clearDataPoints() |
||
119 | { |
||
120 | $this->dataPoints = array(); |
||
121 | |||
122 | return $this; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Increment the value for a key that makes up part of the currently focused |
||
127 | * data object. |
||
128 | * |
||
129 | * @param string $key The index to use |
||
130 | * @param int $value The value to increment by |
||
131 | * @return $this |
||
132 | * @throws \Exception if there is no data point, column or invalid type |
||
133 | */ |
||
134 | public function increment($key, $value = 1) |
||
135 | { |
||
136 | if (!$this->currentDataPoint) { |
||
137 | throw new \Exception('No data point in focus'); |
||
138 | } |
||
139 | |||
140 | View Code Duplication | if (!isset($this->currentDataSet[$this->currentDataPoint][$key])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
141 | throw new \Exception($key . ' has not been defined'); |
||
142 | } |
||
143 | |||
144 | if ($this->currentDataSet[$this->currentDataPoint][$key]['type'] !== 'integer') { |
||
145 | throw new \Exception($key . ' is not a numeric column'); |
||
146 | } |
||
147 | |||
148 | if (!is_int($value)) { |
||
149 | throw new \Exception('Can only increment using a numeric value'); |
||
150 | } |
||
151 | |||
152 | $this->currentDataSet[$this->currentDataPoint][$key]['value'] += $value; |
||
153 | |||
154 | return $this; |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | * Directly set the value for a key that makes up part of the currently focused |
||
159 | * data object. |
||
160 | * |
||
161 | * @param string $key The index to use |
||
162 | * @param string|integer $value The value to set |
||
163 | * @return $this |
||
164 | * @throws \Exception |
||
165 | */ |
||
166 | public function set($key, $value) |
||
167 | { |
||
168 | if (!$this->currentDataPoint) { |
||
169 | throw new \Exception('No data point in focus'); |
||
170 | } |
||
171 | |||
172 | View Code Duplication | if (!isset($this->currentDataSet[$this->currentDataPoint][$key])) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
173 | throw new \Exception($key . ' has not been defined'); |
||
174 | } |
||
175 | $this->currentDataSet[$this->currentDataPoint][$key]['value'] = $value; |
||
176 | |||
177 | return $this; |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Set a focus for the current data object for which data can be manipulated. |
||
182 | * If the key doesn't exist, it will be created using default column values. |
||
183 | * |
||
184 | * @param string $key The reference key to be used |
||
185 | * @return $this |
||
186 | */ |
||
187 | public function setPoint($key) |
||
188 | { |
||
189 | if (!isset($this->currentDataSet[$key])) { |
||
190 | $this->addPoint($key); |
||
191 | } |
||
192 | $this->currentDataPoint = $key; |
||
193 | |||
194 | return $this; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Add a data point which will be shown on the report. This function should be |
||
199 | * used prior to any kind of data manipulation as it will not setup a data |
||
200 | * structure for manipulation. |
||
201 | * |
||
202 | * @param string $key The index to use |
||
203 | * @return $this |
||
204 | */ |
||
205 | public function addPoint($key) |
||
206 | { |
||
207 | if (!in_array($key, $this->dataPoints)) { |
||
208 | $this->dataPoints[] = $key; |
||
209 | $this->currentDataSet[$key] = $this->dataPointMeta; |
||
210 | } |
||
211 | |||
212 | return $this; |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Define a type of data that will be presented on the report or metadata that |
||
217 | * will be used for calculations. In the latter case, within the options array |
||
218 | * set "visible" to false. |
||
219 | * At a minimum, the key needs to be set. In this case, the type will be string |
||
220 | * and the key converted in to a title |
||
221 | * . |
||
222 | * |
||
223 | * @param string $key A reference key for the piece of data |
||
224 | * @param string|integer $defaultValue The default also defines type of column |
||
225 | * @param array $options Additional parameters for the column to use |
||
226 | * |
||
227 | * @return $this |
||
228 | */ |
||
229 | public function column( |
||
230 | $key, |
||
231 | $defaultValue = '', |
||
232 | $options = array() |
||
233 | ) { |
||
234 | |||
235 | $options['value'] = $defaultValue; |
||
236 | |||
237 | // Auto guessing the type? |
||
238 | if (!isset($options['type'])) { |
||
239 | $options['type'] = gettype($defaultValue); |
||
240 | } |
||
241 | // Check whether hidden |
||
242 | if (!isset($options['visible'])) { |
||
243 | $options['visible'] = true; |
||
244 | } |
||
245 | |||
246 | // Does it have a title |
||
247 | if (!isset($options['title']) && $options['visible'] === true) { |
||
248 | $options['title'] = ucwords(str_replace('_', ' ', $key)); |
||
249 | } |
||
250 | |||
251 | $this->dataPointMeta[$key] = $options; |
||
252 | |||
253 | if ($options['visible'] == true) { |
||
254 | $this->columnCount++; |
||
255 | } |
||
256 | |||
257 | return $this; |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Manually set the data which will be used for the current set. when |
||
262 | * using this function, it will expect an associative array of arrays where |
||
263 | * each entry has a further array of values which have a key matching that of |
||
264 | * the meta data. |
||
265 | * TODO - This is quite messy, rewrite more efficiently. |
||
266 | * |
||
267 | * @param array $inputData A set of data which conforms to the column specification |
||
268 | * @return $this |
||
269 | */ |
||
270 | public function setData($inputData) |
||
271 | { |
||
272 | // Combine raw data with the meta data |
||
273 | foreach ($inputData as $key => $values) { |
||
274 | $data = []; |
||
275 | foreach ($this->dataPointMeta as $fieldKey => $field) { |
||
276 | $data[$fieldKey] = array_merge($field, ['value' => $values[$fieldKey]]); |
||
277 | } |
||
278 | $this->currentDataSet[$key] = $data; |
||
279 | } |
||
280 | |||
281 | return $this; |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * Return the information array relating to a specific column |
||
286 | * |
||
287 | * @param string|integer $key |
||
288 | * @return array |
||
289 | * @throws \Exception |
||
290 | */ |
||
291 | public function columnInfo($key) |
||
292 | { |
||
293 | if (isset($this->dataPointMeta[$key])) { |
||
294 | return $this->dataPointMeta[$key]; |
||
295 | } else { |
||
296 | throw new \Exception($key . ' column has not been defined'); |
||
297 | } |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Retrieve the complete meta information relating to a data point |
||
302 | * |
||
303 | * @return array |
||
304 | * @throws \Exception if the current data set is pointer-less |
||
305 | */ |
||
306 | public function getPoint() |
||
307 | { |
||
308 | if (isset($this->currentDataSet[$this->currentDataPoint])) { |
||
309 | return $this->currentDataSet[$this->currentDataPoint]; |
||
310 | } else { |
||
311 | throw new \Exception('No data point to retrieve'); |
||
312 | } |
||
313 | } |
||
314 | |||
315 | /** |
||
316 | * Return a specific piece of data from the current data point |
||
317 | * |
||
318 | * @param string|integer $key |
||
319 | * @return mixed |
||
320 | */ |
||
321 | public function getPointValue($key) |
||
322 | { |
||
323 | $point = $this->getPoint(); |
||
324 | |||
325 | return $point[$key]['value']; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Return the number of data columns that have been defined |
||
330 | * |
||
331 | * @return integer |
||
332 | */ |
||
333 | public function columnCount() |
||
334 | { |
||
335 | return count($this->dataPointMeta); |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * Return the number of data points that have been defined |
||
340 | * |
||
341 | * @return integer |
||
342 | */ |
||
343 | public function dataCount() |
||
344 | { |
||
345 | return count($this->currentDataSet); |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * Return all the column information |
||
350 | * |
||
351 | * @return array |
||
352 | */ |
||
353 | public function getIndex() |
||
354 | { |
||
355 | return $this->dataPointMeta; |
||
356 | } |
||
357 | |||
358 | /** |
||
359 | * Return all the data from the current set |
||
360 | * |
||
361 | * @return array |
||
362 | */ |
||
363 | public function getDataSet() |
||
364 | { |
||
365 | return $this->currentDataSet; |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Return the key for the current data point in focus |
||
370 | * |
||
371 | * @return string |
||
372 | */ |
||
373 | public function getPointKey() |
||
374 | { |
||
375 | return $this->currentDataPoint; |
||
376 | } |
||
377 | } |
||
378 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.