Issues (38)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Service/Meta.php (4 issues)

Upgrade to new PHP Analysis Engine

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
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.

Loading history...
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.

Loading history...
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.

Loading history...
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.

Loading history...
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