Issues (9)

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.

src/HTMLTable/CHTMLTable.php (2 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
namespace Guer\HTMLTable;
3
4
/**
5
 * Class that generates a table in HTML with table data from an array of objects.
6
 *
7
 * Through a table specification array it is possible to set an CSS id or
8
 * a class for the table and a caption.
9
 *
10
 * Through a column specification it is possible to set the column title, set
11
 * a colspan for the table cell and footer cell, through type determine if the
12
 * row of cells belongs to the table body or table foot and through a function
13
 * include advanced settings for a column.
14
 *
15
 * @author Gunnar Eriksson <[email protected]>
16
 */
17
class CHTMLTable
18
{
19
    const FOOTER = 'footer';
20
21
    private $tableSpec;
22
    private $tableHead;
23
    private $tableBody;
24
    private $tableFoot;
25
26
    /**
27
     * Constructor
28
     *
29
     * Creates a table with table head, table body and if specified, a table
30
     * footer. It is possible to specify the table and the tabel cells settings
31
     * per column.
32
     *
33
     * @param string[] $tableSpecs  table settings.
34
     * @param mixed[] $data         table cell data.
35
     * @param mixed[] $columnSpecs  table columns cell settings.
36
     */
37 11
    public function __construct($tableSpecs = [], $data = [], $columnSpecs = [])
38
    {
39 11
        $this->create($tableSpecs, $data, $columnSpecs);
40 11
    }
41
42
    /**
43
     * Creates a table with cell data.
44
     *
45
     * Creates a table with table head, table body with table data and if
46
     * specified, a table footer. It is possible to specify the table and the
47
     * tabel cells settings per column.
48
     *
49
     * @param string[] $tableSpecs  table settings.
50
     * @param mixed[] $data         table cell data.
51
     * @param mixed[] $columnSpecs  table columns cell settings.
52
     *
53
     * @return object the html table object.
54
     */
55 11
    public function create($tableSpecs = [], $data = [], $columnSpecs = [])
56
    {
57 11
        $this->resetTableTags();
58 11
        $this->setTableSpecifications($tableSpecs);
59
60 11
        $this->createTableHead($data, $columnSpecs);
61 11
        $this->createTableBody($data, $columnSpecs);
62 11
        $this->createTableFooter($columnSpecs);
63
64 11
        return $this;
65
    }
66
67
    /**
68
     * Helper method to reset main parts of table tags.
69
     *
70
     * Sets the table head, table body and table foot tag to null.
71
     *
72
     * @return void
73
     */
74 11
    private function resetTableTags()
75
    {
76 11
        $this->tableHead = null;
77 11
        $this->tableBody = null;
78 11
        $this->tableFoot = null;
79 11
    }
80
81
    /**
82
     * Helper method to set the table specifications.
83
     *
84
     * Merges the table specifications with the default specifications.
85
     * Default table CSS id is html-table.
86
     *
87
     * @param  string[] $tableSpec the table specification.
88
     *
89
     * @return void
90
     */
91 11
    private function setTableSpecifications($tableSpec)
92
    {
93
        $defaults = [
94
            // Always have a id for the form
95 11
            'id' => 'html-table',
96 11
        ];
97
98 11
        if ($this->isClassPresent($tableSpec)) {
99 1
            $tableSpec = $this->removeId($tableSpec);
100 1
        }
101
102 11
        $this->tableSpec = array_merge($defaults, $tableSpec);
103 11
    }
104
105
    /**
106
     * Helper method to check if a CSS class tag is present
107
     *
108
     * Checks if a CSS class tag is present in the table specification.
109
     *
110
     * @param  string[] $tableSpec the table specification.
111
     *
112
     * @return boolean  true if class is present in the table specification,
113
     *                  false otherwise.
114
     */
115 11
    private function isClassPresent($tableSpec)
116
    {
117 11
        return isset($tableSpec['class']) ? true : false;
118
    }
119
120
    /**
121
     * Helper method to reset the id tag.
122
     *
123
     * Sets the CSS id tag to null.
124
     *
125
     * @param  string[] $tableSpec the table specification.
126
     *
127
     * @return string[] the table specification without the CSS id tag.
128
     */
129 1
    private function removeId($tableSpec) {
130 1
        $tableSpec['id'] = null;
131
132 1
        return $tableSpec;
133
    }
134
135
    /**
136
     * Helper method to create the table head.
137
     *
138
     * Creates the table head. The title of the columns are set according to
139
     * the table tag in the column specifications. Otherwise, the title is set
140
     * to the keys name in the table cell data array.
141
     *
142
     * @param  mixed[]  $data        table cell data.
143
     * @param  mixed[]  $columnSpecs table columns cell settings.
144
     *
145
     * @return void
146
     */
147 11
    private function createTableHead($data, $columnSpecs)
148
    {
149 11
        $this->tableHead = "\n<thead>";
150 11
        $this->tableHead .= "\n<tr>";
151
152 11
        if (empty($columnSpecs))
153 11
        {
154 11
            $this->setColumnTitlesFromData($data);
155 11
        } else {
156 7
            $this->setColumnTitlesFromColumnSpecifications($columnSpecs);
157
        }
158
159 11
        $this->tableHead .= "\n</tr>";
160 11
        $this->tableHead .= "\n</thead>";
161 11
    }
162
163
    /**
164
     * Helper method to set the column titles from the data array.
165
     *
166
     * Uses the first row in the table cell data array to set the titles of
167
     * the columns. The name of the columns are the key name for the objects in
168
     * the array containing data for the table.
169
     *
170
     * @param  mixed[]  $data   table cell data.
171
     *
172
     * @return void
173
     */
174 11
    private function setColumnTitlesFromData($data)
175
    {
176 11
        $firstRow = isset($data[0]) ? $data[0] : [];
177 11
        foreach ($firstRow as $key => $value) {
178 4
            $this->tableHead .= "\n<th>";
179 4
            $this->tableHead .= htmlentities($key, null, 'UTF-8');
180 4
            $this->tableHead .= "</th>";
181 11
        }
182 11
    }
183
184
    /**
185
     * Helper method to set the column titles from column specifications.
186
     *
187
     * Uses column specifications to set the name of the columns in the table
188
     * head.
189
     *
190
     * @param  mixed[]  $columnSpecs    table columns cell settings
191
     *
192
     * @return void
193
     */
194 7
    private function setColumnTitlesFromColumnSpecifications($columnSpecs)
195
    {
196 7
        foreach ($columnSpecs as $key => $columnSpec) {
197 7
            if (!$this->isTableFooter($columnSpec)) {
198 7
                $this->tableHead .= "\n<th>";
199 7
                $this->tableHead .= $this->getTitle($key, $columnSpec);
200 7
                $this->tableHead .= "</th>";
201 7
            }
202 7
        }
203 7
    }
204
205
    /**
206
     * Helper method to check if the column cell belongs to the footer.
207
     *
208
     * Checks the type tag, in the column specification for one column, if the
209
     * tag is present and set to footer.
210
     *
211
     * @param  mixed[]  $columnSpec cell settings for one column.
212
     *
213
     * @return boolean true if the cell type belongs to the footer, false otherwise.
214
     */
215 7
    private function isTableFooter($columnSpec)
216
    {
217 7
        $isFooter = false;
218 7
        if (isset($columnSpec['type'])) {
219 2
            if (strcmp($columnSpec['type'], self::FOOTER) === 0) {
220 2
                $isFooter = true;
221 2
            }
222 2
        }
223
224 7
        return $isFooter;
225
    }
226
227
    /**
228
     * Helper method to get title from a column specification, if specified.
229
     *
230
     * Uses the title tag in the column specification for one column to get
231
     * the title. If the title tag is not set, the title is the key for the
232
     * objects int the array containing data for the table.
233
     *
234
     * @param  string   $key        the name of the key for the table cell data.
235
     * @param  mixed[]  $columnSpec cell settings for one column.
236
     *
237
     * @return string[] the name from the title tag in the cell specification.
238
     *                  Otherwise, the table cell data key name.
239
     */
240 7
    private function getTitle($key, $columnSpec)
241
    {
242 7
        return isset($columnSpec['title']) ? $columnSpec['title'] : $key;
243
    }
244
245
    /**
246
     * Helper method to create the table body with table cell data.
247
     *
248
     * Sets the table cell data in the table body.
249
     *
250
     * @param  mixed[] $data        table cell data.
251
     * @param  mixed[] $columnSpecs table columns cell settings.
252
     *
253
     * @return void
254
     */
255 11
    private function createTableBody($data, $columnSpecs)
256
    {
257 11
        $this->setTableData($data, $columnSpecs);
258 11
        if (isset($this->tableBody)) {
259 11
            $this->tableBody = "\n<tbody>" . $this->tableBody . "\n</tbody>";
260 11
        }
261 11
    }
262
263
    /**
264
     * Helper method to set table data in table body.
265
     *
266
     * Sets table data according to the column specifications, if it is
267
     * specified. Otherwise it sets the data as it is stored in the data array.
268
     *
269
     * @param  mixed[] $data        table cell data.
270
     * @param  mixed[] $columnSpecs table columns cell settings.
271
     *
272
     * @return void
273
     */
274 11
    private function setTableData($data, $columnSpecs)
275
    {
276 11
        if (empty($columnSpecs)) {
277 11
            $this->setTableDataFromData($data);
278 11
        } else {
279 7
            $this->setTableDataAsSpecified($data, $columnSpecs);
280
        }
281 11
    }
282
283
    /**
284
     * Helper method to set table data from the data array.
285
     *
286
     * Sets table data from the data array.
287
     *
288
     * @param  mixed[]  $data   table cell data.
289
     *
290
     * @return void
291
     */
292 11
    private function setTableDataFromData($data)
293
    {
294 11
        foreach ($data as $row) {
295 4
            $this->tableBody .= "\n<tr>";
296 4
            foreach ($row as $value) {
297 4
                $this->tableBody .= "\n<td>";
298 4
                $this->tableBody .= htmlentities($value, null, 'UTF-8');
299 4
                $this->tableBody .= "</td>";
300 4
            }
301 4
            $this->tableBody .= "\n</tr>";
302 11
        }
303 11
    }
304
305
    /**
306
     * Helper method to set table data according to the column specifications.
307
     *
308
     * Sets the table data according to the column specifications, if the cell
309
     * does not belong to the footer. Adds a colspan tag, if it is specified
310
     * for the cell in the column.
311
     *
312
     * @param  mixed[] $data         table cell data.
313
     * @param  mixed[] $columnSpecs  table columns cell settings.
314
     *
315
     * @return void
316
     */
317 7
    private function setTableDataAsSpecified($data, $columnSpecs)
318
    {
319 7
        foreach ($data as $row) {
320 7
            $this->tableBody .= "\n<tr>";
321 7
            foreach ($columnSpecs as $key => $columnSpec) {
322 7 View Code Duplication
                if (!$this->isTableFooter($columnSpec)) {
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...
323 7
                    $colspan = $this->getColspan($columnSpec);
324 7
                    $this->tableBody .= "\n<td{$colspan}>";
325 7
                    $this->tableBody .= $this->getValue($row, $key, $columnSpec);
326 7
                    $this->tableBody .= "</td>";
327 7
                }
328 7
            }
329 7
            $this->tableBody .= "\n</tr>";
330 7
        }
331 7
    }
332
333
    /**
334
     * Helper method to get the colspan value, if specified in the column
335
     * specification for the cell.
336
     *
337
     * @param  mixed[]  $columnSpec cell settings for one column.
338
     *
339
     * @return int the colspan value if specified. Otherwise null.
340
     */
341 7
    private function getColspan($columnSpec)
342
    {
343 7
        return isset($columnSpec['colspan']) ? " colspan='{$columnSpec['colspan']}'" : null;
344
    }
345
346
    /**
347
     * Helper method to get the value for a specific position in one row in
348
     * the data array.
349
     *
350
     * Gets the data from a specific position in one row in the data array.
351
     * If a function is specified for the cell in the column, the data is
352
     * runned through the function before it is returned.If the object key is
353
     * specified to object, the reference to the object is fetched from the
354
     * array of objects.
355
     *
356
     * @param  object   $row        one row of in the array of table data.
357
     * @param  string   $key        the name of the key in the associative data array.
358
     * @param  mixed[]  $columnSpec cell settings for one column.
359
     */
360 7
    private function getValue($row, $key, $columnSpec)
361
    {
362 7
        if ($this->isFunctionSpecified($columnSpec)) {
363 3
            if ($this->isObjectSpecifiedAsKey($key)) {
364 1
                $dataValue = isset($row) ? $row : "";
365 1
            } else {
366 2
                $dataValue = isset($row->$key) ? $row->$key : "";
367
            }
368
369 3
            return $this->getValueThroughFunction($columnSpec, $dataValue);
370
        } else {
371 7
            return isset($row->$key) ? htmlentities($row->$key, null, 'UTF-8') : "";
372
        }
373
    }
374
375
    /**
376
     * Helper method t check if the function tag is specified for the cells in
377
     * one column.
378
     *
379
     * Checks if the function tag is set for the cell in one column.
380
     *
381
     * @param  mixed[]  $columnSpec     cell settings for one column.
382
     *
383
     * @return boolean true if a function is connected to the cell, false otherwise.
384
     */
385 7
    private function isFunctionSpecified($columnSpec)
386
    {
387 7
        return isset($columnSpec['function']) ? true : false;
388
    }
389
390
    /**
391
     * Helper method to check if the object key is specified to object.
392
     *
393
     * Checks if the object key starts with object. The check is case insensitive.
394
     *
395
     * @param  string  $key the name of the key for the object.
396
     *
397
     * @return boolean true if the key starts with object, false otherwise.
398
     */
399 3
    private function isObjectSpecifiedAsKey($key)
400
    {
401 3
        $keyRest = substr($key, 0, 6);
402
403 3
        return strcasecmp($keyRest, "object") === 0 ? true : false;
404
    }
405
406
    /**
407
     * Helper method to run the value through a function before it is returned.
408
     *
409
     * Runs the value through a function, if a function is connected to the cell
410
     * in the column. If not function is connected to the cell through the
411
     * column specification, the value is returned as it is.
412
     *
413
     * WHEN USING A FUNCTION, NO DATA IS CHECKED. TO BE PROTECTED AGAINST
414
     * HARMFUL DATA, THE PROTECTION MUST BE ADDED WHEN THE FUNCTION IS SPECIFIED
415
     * WHEN CREATING THE TABLE!
416
     *
417
     * @param mixed[]   $columnSpec     cell settings for one column
418
     * @param mixed     $dataValue      the value to run through function, if specified.
419
     *
420
     * @return the value.
421
     */
422 3
    private function getValueThroughFunction($columnSpec, $dataValue)
423
    {
424 3
        if (!empty($columnSpec['function'])) {
425 2
            return call_user_func($columnSpec['function'], $dataValue);
426
        } else {
427 1
            return $dataValue;
428
        }
429
    }
430
431
    /**
432
     * Helper method to create table footer with data.
433
     *
434
     * Creates table footer if the cell settings for the column is set to
435
     * footer in the column specifications.
436
     * Adds a colspan tag, if it is specified for the cell in the column.
437
     *
438
     * @param  mixed[] $columnSpecs table columns cell settings.
439
     *
440
     * @return void
441
     */
442 11
    private function createTableFooter($columnSpecs)
443
    {
444 11
        foreach ($columnSpecs as $columnSpec) {
445 7 View Code Duplication
            if ($this->isTableFooter($columnSpec)) {
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...
446 2
                $colspan = $this->getColspan($columnSpec);
447 2
                $this->tableFoot .= "\n<td{$colspan}>";
448 2
                $this->tableFoot .= $this->getFooterData($columnSpec);
449 2
                $this->tableFoot .= "</td>";
450 2
            }
451 11
        }
452
453 11
        if (isset($this->tableFoot)) {
454 2
            $this->tableFoot = "\n<tfoot>\n<tr>" . $this->tableFoot . "\n</tr>\n</tfoot>";
455 2
        }
456 11
    }
457
458
    /**
459
     * Helper method to get table footer data.
460
     *
461
     * Gets table footer data from the column specification. Checks if the
462
     * value should be fetched from a function or from the value tag.
463
     * If either the function or the value specified, an empty string is
464
     * returned.
465
     *
466
     * @param  mixed[] $columnSpec  cell settings for one column.
467
     *
468
     * @return mixed    the cell data value.
469
     */
470 2
    private function getFooterData($columnSpec)
471
    {
472 2
        if ($this->isFunctionSpecified($columnSpec)) {
473 1
            return call_user_func($columnSpec['function']);
474
        } else {
475 1
            return isset($columnSpec['value']) ? $columnSpec['value'] : "";
476
        }
477
    }
478
479
    /**
480
     * Gets the table.
481
     *
482
     * Gets the table with table data.
483
     *
484
     * @return html     the table with table data.
485
     */
486 11
    public function getHTMLTable()
487
    {
488 11
        $id = isset($this->tableSpec['id']) ? " id='{$this->tableSpec['id']}'" : null;
489 11
        $class = isset($this->tableSpec['class']) ? " class='{$this->tableSpec['class']}'" : null;
490 11
        $caption = isset($this->tableSpec['caption']) ? "<caption>{$this->tableSpec['caption']}</caption>" : null;
491
492 11
        $htmlTable = "<table{$id}{$class}>";
493 11
        $htmlTable .= $caption;
494 11
        $htmlTable .= $this->tableHead;
495 11
        $htmlTable .= $this->tableBody;
496 11
        $htmlTable .= $this->tableFoot;
497 11
        $htmlTable .= "\n</table>";
498
499 11
        return $htmlTable;
500
    }
501
}
502