Issues (68)

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/Helpers/Html.php (9 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
 * Scabbia2 Helpers Component
4
 * https://github.com/eserozvataf/scabbia2
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @link        https://github.com/eserozvataf/scabbia2-helpers for the canonical source repository
10
 * @copyright   2010-2016 Eser Ozvataf. (http://eser.ozvataf.com/)
11
 * @license     http://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0
12
 */
13
14
namespace Scabbia\Helpers;
15
16
use Scabbia\Helpers\Arrays;
17
use Scabbia\Helpers\String;
18
19
/**
20
 * A bunch of utility methods for creating html elements
21
 *
22
 * @package     Scabbia\Helpers
23
 * @author      Eser Ozvataf <[email protected]>
24
 * @since       1.0.0
25
 *
26
 * @scabbia-compile
27
 *
28
 * @todo form open
29
 * @todo form fields
30
 * @todo form csrf protection
31
 * @todo Html::list (<li> every row, nested)
32
 * @todo Html::br (<br /> implode)
33
 * @todo Html::image
34
 * @todo Html::anchor
35
 * @todo Html::anchorEmail
36
 * @todo Html::textarea
37
 * @todo Html::button
38
 */
39
class Html
40
{
41
    /**
42
     * Default variables for Html utility set
43
     *
44
     * @type array $defaults array of default variables
45
     */
46
    public static $defaults = [
47
        "pager_pagesize" => 10,
48
        "pager_numlinks" => 10,
49
50
        "pager_firstlast" => true,
51
        "pager_first" => "&lt;&lt;",
52
        "pager_prev" => "&lt;",
53
        "pager_next" => "&gt;",
54
        "pager_last" => "&gt;&gt;",
55
56
        "pager_divider" => "",
57
        "pager_dots" => " ... ",
58
59
        "table_table" => "<table>",
60
        "table_header" => "<th>{value}</th>",
61
        "table_cell" => "<td>{value}</td>"
62
    ];
63
64
    /**
65
     * Set of attribute placement order
66
     *
67
     * @type array $attributeOrder array of attribute orders
68
     */
69
    public static $attributeOrder = [
70
        "action", "method", "type", "id", "name", "value",
71
        "href", "src", "width", "height", "cols", "rows",
72
        "size", "maxlength", "rel", "media", "accept-charset",
73
        "accept", "tabindex", "accesskey", "alt", "title", "class",
74
        "style", "selected", "checked", "readonly", "disabled"
75
    ];
76
77
78
    /**
79
     * Constructor to prevent new instances of Html class
80
     *
81
     * @return Html
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
82
     */
83
    final private function __construct()
84
    {
85
    }
86
87
    /**
88
     * Clone method to prevent duplication of Html class
89
     *
90
     * @return Html
91
     */
92
    final private function __clone()
93
    {
94
    }
95
96
    /**
97
     * Unserialization method to prevent restoration of Html class
98
     *
99
     * @return Html
100
     */
101
    final private function __wakeup()
102
    {
103
    }
104
105
    /**
106
     * Sets the default variables
107
     *
108
     * @param array $uDefaults variables to be set
109
     *
110
     * @return void
111
     */
112
    public static function setDefaults($uDefaults)
113
    {
114
        self::$defaults = $uDefaults + self::$defaults;
115
    }
116
117
    /**
118
     * Creates an Html tag
119
     *
120
     * @param string      $uName       name of the element
121
     * @param array       $uAttributes set of the tag attributes
122
     * @param null|string $uValue      value
123
     *
124
     * @return string html output
125
     */
126
    public static function tag($uName, array $uAttributes = [], $uValue = null)
127
    {
128
        $tReturn = "<{$uName}";
129
        if (count($uAttributes) > 0) {
130
            $tReturn .= " " . self::attributes($uAttributes);
131
        }
132
133
        if ($uValue === null) {
134
            $tReturn .= " />";
135
        } else {
136
            $tReturn .= ">{$uValue}</{$uName}>";
137
        }
138
139
        return $tReturn;
140
    }
141
142
    /**
143
     * Creates attributes array
144
     *
145
     * @param array $uAttributes set of the tag attributes
146
     *
147
     * @return string html output
148
     */
149
    public static function attributes(array $uAttributes)
150
    {
151
        $tAttributes = Arrays::sortByPriority($uAttributes, self::$attributeOrder);
152
153
        $tReturn = [];
154
        foreach ($tAttributes as $tKey => $tValue) {
155
            if ($tValue === null) {
156
                $tReturn[] = "{$tKey}=\"{$tKey}\"";
157
                continue;
158
            }
159
160
            $tReturn[] = "{$tKey}=\"" . String::escapeHtml($tValue) . "\"";
161
        }
162
163
        return implode(" ", $tReturn);
164
    }
165
166
    /**
167
     * Creates options array for select element
168
     *
169
     * @param array  $uOptions set of values
170
     * @param mixed  $uDefault default selected value
171
     * @param mixed  $uField   field key for array values
172
     * @param string $uExtra   additional markup for each option tag
173
     *
174
     * @return string html output
175
     */
176
    public static function selectOptions(array $uOptions, $uDefault = null, $uField = null, $uExtra = "")
177
    {
178
        $tOutput = "";
179
180
        foreach ($uOptions as $tKey => $tVal) {
181
            $tOutput .= "<option value=\"" . String::dquote($tKey) . "\"";
182
            if ($uDefault === $tKey) {
183
                $tOutput .= " selected=\"selected\"";
184
            }
185
186
            $tOutput .= "{$uExtra}>" . ($uField !== null ? $tVal[$uField] : $tVal) . "</option>";
187
        }
188
189
        return $tOutput;
190
    }
191
192
    /**
193
     * Creates options array for select element and returns it in array
194
     *
195
     * @param array  $uOptions set of values
196
     * @param mixed  $uDefault default selected value
197
     * @param mixed  $uField   field key for array values
198
     * @param string $uExtra   additional markup for each option tag
199
     *
200
     * @return string set of html outputs
201
     */
202
    public static function selectOptionsArray(array $uOptions, $uDefault = null, $uField = null, $uExtra = "")
203
    {
204
        $tOutput = [];
205
206
        foreach ($uOptions as $tKey => $tVal) {
207
            $tItem = "<option value=\"" . String::dquote($tKey) . "\"";
208
            if ($uDefault === $tKey) {
209
                $tItem .= " selected=\"selected\"";
210
            }
211
212
            $tItem .= "{$uExtra}>" . ($uField !== null ? $tVal[$uField] : $tVal) . "</option>";
213
            $tOutput[] = $tItem;
214
        }
215
216
        return $tOutput;
217
    }
218
219
    /**
220
     * Creates options array for input type="radio" element
221
     *
222
     * @param string $uName    name of the element
223
     * @param array  $uOptions set of values
224
     * @param mixed  $uDefault default selected value
225
     * @param mixed  $uField   field key for array values
226
     * @param string $uExtra   additional markup for each option tag
227
     *
228
     * @return string html output
229
     */
230
    public static function radioOptions($uName, array $uOptions, $uDefault = null, $uField = null, $uExtra = "")
231
    {
232
        $tOutput = "";
233
234
        foreach ($uOptions as $tKey => $tVal) {
235
            $tOutput .= "<label";
236
237
            if ($uDefault === $tKey) {
238
                $tOutput .= " class=\"selected\"";
239
            }
240
241
            $tOutput .= "><input type=\"radio\" name=\"" .
242
                String::dquote($uName) .
243
                "\" value=\"" . String::dquote($tKey) . "\"";
244
245
            if ($uDefault === $tKey) {
246
                $tOutput .= " checked=\"checked\"";
247
            }
248
249
            if (strlen($uExtra) > 0) {
250
                $tOutput .= " {$uExtra}";
251
            }
252
253
            $tOutput .= " />" . ($uField !== null ? $tVal[$uField] : $tVal) . "</label>";
254
        }
255
256
        return $tOutput;
257
    }
258
259
    /**
260
     * Creates options array for input type="radio" element and returns it in array
261
     *
262
     * @param string $uName    name of the element
263
     * @param array  $uOptions set of values
264
     * @param mixed  $uDefault default selected value
265
     * @param mixed  $uField   field key for array values
266
     * @param string $uExtra   additional markup for each option tag
267
     *
268
     * @return string set of html outputs
269
     */
270
    public static function radioOptionsArray($uName, array $uOptions, $uDefault = null, $uField = null, $uExtra = "")
271
    {
272
        $tOutput = [];
273
274
        foreach ($uOptions as $tKey => $tVal) {
275
            $tItem = "<label";
276
277
            if ($uDefault === $tKey) {
278
                $tItem .= " class=\"selected\"";
279
            }
280
281
            $tItem .= "><input type=\"radio\" name=\"" .
282
                String::dquote($uName) . "\" value=\"" .
283
                String::dquote($tKey) . "\"";
284
285
            if ($uDefault === $tKey) {
286
                $tItem .= " checked=\"checked\"";
287
            }
288
289
            if (strlen($uExtra) > 0) {
290
                $tOutput .= " {$uExtra}";
291
            }
292
293
            $tItem .= " />" . ($uField !== null ? $tVal[$uField] : $tVal) . "</label>";
294
            $tOutput[] = $tItem;
295
        }
296
297
        return $tOutput;
298
    }
299
300
    /**
301
     * Creates a textbox element
302
     *
303
     * @param string $uName       name of the element
304
     * @param mixed  $uValue      default value
305
     * @param array  $uAttributes set of the tag attributes
306
     *
307
     * @return string html output
308
     */
309
    public static function textBox($uName, $uValue = "", array $uAttributes = [])
310
    {
311
        $uAttributes["name"] = $uName;
312
        $uAttributes["value"] = $uValue;
313
314
        $tOutput = "<input type=\"text\" " . self::attributes($uAttributes) . " />";
315
316
        return $tOutput;
317
    }
318
319
    /**
320
     * Creates a checkbox element
321
     *
322
     * @param string $uName         name of the element
323
     * @param mixed  $uValue        value
324
     * @param mixed  $uCurrentValue default value
325
     * @param string $uText         caption
326
     * @param array  $uAttributes   set of the tag attributes
327
     *
328
     * @return string html output
329
     */
330
    public static function checkBox($uName, $uValue, $uCurrentValue = null, $uText = null, array $uAttributes = [])
331
    {
332
        $uAttributes["name"] = $uName;
333
        $uAttributes["value"] = $uValue;
334
335
        if ($uCurrentValue === $uValue) {
336
            $uAttributes["checked"] = "checked";
337
        }
338
339
        $tOutput = "<label><input type=\"checkbox\" " . self::attributes($uAttributes) . " />";
340
341
        if ($uText !== null) {
342
            $tOutput .= $uText;
343
        }
344
345
        $tOutput .= "</label>";
346
347
        return $tOutput;
348
    }
349
350
    /**
351
     * Returns doctype header to be printed out
352
     *
353
     * @param string $uType the type of the document
354
     *
355
     * @return bool|string html output
356
     */
357
    public static function doctype($uType = "html5")
358
    {
359
        if ($uType === "html5" || $uType === "xhtml5") {
360
            return "<!DOCTYPE html>" . PHP_EOL;
361
        } elseif ($uType ===  "xhtml11" || $uType === "xhtml1.1") {
362
            return
363
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" " .
364
                "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" .
365
                PHP_EOL;
366
        } elseif ($uType === "xhtml1" || $uType === "xhtml1-strict") {
367
            return
368
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" " .
369
                "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" .
370
                PHP_EOL;
371
        } elseif ($uType === "xhtml1-trans") {
372
            return
373
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " .
374
                "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" .
375
                PHP_EOL;
376
        } elseif ($uType === "xhtml1-frame") {
377
            return
378
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" " .
379
                "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">" .
380
                PHP_EOL;
381
        } elseif ($uType === "html4-strict") {
382
            return
383
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" " .
384
                "\"http://www.w3.org/TR/html4/strict.dtd\">" .
385
                PHP_EOL;
386
        } elseif ($uType === "html4" || $uType === "html4-trans") {
387
            return
388
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" " .
389
                "\"http://www.w3.org/TR/html4/loose.dtd\">" .
390
                PHP_EOL;
391
        } elseif ($uType === "html4-frame") {
392
            return
393
                "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" " .
394
                "\"http://www.w3.org/TR/html4/frameset.dtd\">" .
395
                PHP_EOL;
396
        }
397
398
        return false;
399
    }
400
401
    /**
402
     * Creates a script element
403
     *
404
     * @param string $uHref       hypertext reference of script file
405
     * @param array  $uAttributes set of the tag attributes
406
     *
407
     * @return string html output
408
     */
409 View Code Duplication
    public static function script($uHref, array $uAttributes = [])
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...
410
    {
411
        $uAttributes["src"] = $uHref;
412
413
        $tOutput = "<script " . self::attributes($uAttributes) . "></script>";
414
415
        return $tOutput;
416
    }
417
418
    /**
419
     * Creates an inline script element
420
     *
421
     * @param string $uScriptContent  script content
422
     * @param array  $uAttributes     set of the tag attributes
423
     *
424
     * @return string html output
425
     */
426 View Code Duplication
    public static function scriptInline($uScriptContent, array $uAttributes = [])
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...
427
    {
428
        $uAttributes["src"] = $uHref;
0 ignored issues
show
The variable $uHref does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
429
430
        $tOutput = "<script " . self::attributes($uAttributes) . ">{$uScriptContent}</script>";
431
432
        return $tOutput;
433
    }
434
435
    /**
436
     * Creates a link element
437
     *
438
     * @param string $uRelation   relation type
439
     * @param string $uHref       hypertext reference of linked file
440
     * @param array  $uAttributes set of the tag attributes
441
     *
442
     * @return string html output
443
     */
444 View Code Duplication
    public static function link($uRelation, $uHref, array $uAttributes = [])
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...
445
    {
446
        $uAttributes["rel"] = $uRelation;
447
        $uAttributes["href"] = $uHref;
448
449
        $tOutput = "<link " . self::attributes($uAttributes) . " />";
450
451
        return $tOutput;
452
    }
453
454
    /**
455
     * Creates a link element to link a stylesheet file
456
     *
457
     * @param string $uHref       hypertext reference of linked file
458
     * @param string $uMediaType  target media type
459
     * @param array  $uAttributes set of the tag attributes
460
     *
461
     * @return string html output
462
     */
463
    public static function linkStyleSheet($uHref, $uMediaType = "all", array $uAttributes = [])
464
    {
465
        $uAttributes["rel"] = "stylesheet";
466
        $uAttributes["media"] = $uMediaType;
467
        $uAttributes["href"] = $uHref;
468
469
        $tOutput = "<link " . self::attributes($uAttributes) . " />";
470
471
        return $tOutput;
472
    }
473
474
    /**
475
     * Creates a pager widget
476
     *
477
     * @param int   $uCurrent   current page
478
     * @param int   $uTotal     total number of pages
479
     * @param array $uVariables variables
480
     *
481
     * @return string html output
482
     */
483
    public static function pager($uCurrent, $uTotal, array $uVariables)
484
    {
485
        $uVariables = $uVariables + self::$defaults;
486
        $tPages = ceil($uTotal / $uVariables["pager_pagesize"]);
487
488
        if (!isset($uVariables["link"])) {
489
            $uVariables["link"] = "<a href=\"{root}/{page}\" class=\"pagerlink\">{pagetext}</a>";
490
        }
491
492
        if (!isset($uVariables["passivelink"])) {
493
            $uVariables["passivelink"] = $uVariables["link"];
494
        }
495
496
        if (!isset($uVariables["activelink"])) {
497
            $uVariables["activelink"] = $uVariables["passivelink"];
498
        }
499
500
        if ($uCurrent <= 0) {
501
            $uCurrent = 1;
502
        } elseif ($uCurrent > $uTotal) {
503
            $uCurrent = $uTotal;
504
        }
505
506
        $tHalf = floor($uVariables["pager_numlinks"] * 0.5);
507
        $tStart = $uCurrent - $tHalf;
508
        $tEnd = $uCurrent + $tHalf - 1;
509
510
        if ($tStart < 1) {
511
            $tEnd += abs($tStart) + 1;
512
            $tStart = 1;
513
        }
514
515
        if ($tEnd > $tPages) {
516
            if ($tStart - $tEnd - $tPages > 0) {
517
                $tStart -= $tEnd - $tPages;
518
            }
519
            $tEnd = $tPages;
520
        }
521
522
        $tResult = "";
523
524
        if ($tPages > 1) {
525
            if ($uCurrent <= 1) {
526
                if ($uVariables["pager_firstlast"]) {
527
                    $tResult .= String::format(
528
                        $uVariables["passivelink"],
529
                        [
530
                            "page" => "1",
531
                            "pagetext" => $uVariables["pager_first"]
532
                        ]
533
                    );
534
                }
535
                $tResult .= String::format(
536
                    $uVariables["passivelink"],
537
                    [
538
                        "page" => "1",
539
                        "pagetext" => $uVariables["pager_prev"]
540
                    ]
541
                );
542 View Code Duplication
            } else {
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...
543
                if ($uVariables["pager_firstlast"]) {
544
                    $tResult .= String::format(
545
                        $uVariables["link"],
546
                        [
547
                            "page" => "1",
548
                            "pagetext" => $uVariables["pager_first"]
549
                        ]
550
                    );
551
                }
552
                $tResult .= String::format(
553
                    $uVariables["link"],
554
                    [
555
                        "page" => $uCurrent - 1,
556
                        "pagetext" => $uVariables["pager_prev"]
557
                    ]
558
                );
559
            }
560
561
            if ($tStart > 1) {
562
                $tResult .= $uVariables["pager_dots"];
563
            } else {
564
                $tResult .= $uVariables["pager_divider"];
565
            }
566
        }
567
568
        for ($i = $tStart; $i <= $tEnd; $i++) {
569
            if ($uCurrent === $i) {
570
                $tResult .= String::format(
571
                    $uVariables["activelink"],
572
                    [
573
                        "page" => $i,
574
                        "pagetext" => $i
575
                    ]
576
                );
577
            } else {
578
                $tResult .= String::format(
579
                    $uVariables["link"],
580
                    [
581
                        "page" => $i,
582
                        "pagetext" => $i
583
                    ]
584
                );
585
            }
586
587
            if ($i !== $tEnd) {
588
                $tResult .= $uVariables["pager_divider"];
589
            }
590
        }
591
592
        if ($tPages > 1) {
593
            if ($tEnd < $tPages) {
594
                $tResult .= $uVariables["pager_dots"];
595
            } else {
596
                $tResult .= $uVariables["pager_divider"];
597
            }
598
599
            if ($uCurrent >= $tPages) {
600
                $tResult .= String::format(
601
                    $uVariables["passivelink"],
602
                    [
603
                        "page" => $tPages,
604
                        "pagetext" => $uVariables["pager_next"]
605
                    ]
606
                );
607
                if ($uVariables["pager_firstlast"]) {
608
                    $tResult .= String::format(
609
                        $uVariables["passivelink"],
610
                        [
611
                            "page" => $tPages,
612
                            "pagetext" => $uVariables["pager_last"]
613
                        ]
614
                    );
615
                }
616 View Code Duplication
            } else {
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...
617
                $tResult .= String::format(
618
                    $uVariables["link"],
619
                    [
620
                        "page" => $uCurrent + 1,
621
                        "pagetext" => $uVariables["pager_next"]
622
                    ]
623
                );
624
                if ($uVariables["pager_firstlast"]) {
625
                    $tResult .= String::format(
626
                        $uVariables["link"],
627
                        [
628
                            "page" => $tPages,
629
                            "pagetext" => $uVariables["pager_last"]
630
                        ]
631
                    );
632
                }
633
            }
634
        }
635
636
        return $tResult;
637
    }
638
639
    /**
640
     * Creates a table widget
641
     *
642
     * @param array    $uHeaders   table headers
643
     * @param iterable $uData      table data
644
     * @param array    $uVariables variables
645
     *
646
     * @return string html output
647
     */
648
    public static function table(array $uHeaders, $uData, array $uVariables)
649
    {
650
        $uVariables = $uVariables + self::$defaults;
651
        $tResult = String::format($uVariables["table_table"], []);
652
653 View Code Duplication
        if (count($uHeaders) > 0) {
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...
654
            $tResult .= "<tr>";
655
            foreach ($uHeaders as $tColumn) {
656
                $tResult .= String::format($uVariables["table_header"], ["value" => $tColumn]);
657
            }
658
            $tResult .= "</tr>";
659
        }
660
661
        $tCount = 0;
662
        foreach ($uData as $tRow) {
663
            if (isset($uVariables["table_row_func"])) {
664
                $tResult .= call_user_func($uVariables["table_row_func"], $tRow, $tCount++);
665
            } else {
666
                if (isset($uVariables["row"])) {
667
                    $tResult .= String::format($uVariables["table_row"], $tRow);
668 View Code Duplication
                } else {
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...
669
                    $tResult .= "<tr>";
670
671
                    foreach ($tRow as $tColumn) {
672
                        $tResult .= String::format($uVariables["table_cell"], ["value" => $tColumn]);
673
                    }
674
675
                    $tResult .= "</tr>";
676
                }
677
            }
678
        }
679
680
        $tResult .= "</table>";
681
682
        return $tResult;
683
    }
684
}
685