Passed
Pull Request — develop (#262)
by Felipe
04:12
created

HTMLTableController::getForm()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
// declare(strict_types=1);
4
5
/**
6
 * PHPPgAdmin vv6.0.0-RC8-16-g13de173f
7
 *
8
 */
0 ignored issues
show
Coding Style introduced by
Additional blank lines found at end of doc comment
Loading history...
9
10
namespace PHPPgAdmin\XHtml;
11
12
use PHPPgAdmin\Decorators\Decorator;
13
14
/**
15
 * Class to render tables. Formerly part of Misc.php.
16
 */
17
class HTMLTableController extends HTMLController
18
{
19
    public $controller_name = 'HTMLTableController';
20
21
    protected $ma = [];
22
23
    protected $plugin_functions_parameters = [];
24
25
    protected $has_ma = false;
26
27
    protected $tabledata;
28
29
    protected $columns;
30
31
    protected $actions;
32
33
    protected $place;
34
35
    protected $nodata;
36
37
    protected $pre_fn;
38
39
    /**
40
     * Display a table of data.
41
     *
42
     * @param \PHPPgAdmin\ADORecordSet|\PHPPgAdmin\ArrayRecordSet $tabledata a set of data to be formatted, as returned by $data->getDatabases() etc
43
     * @param array                                               $columns   An associative array of columns to be displayed:
44
     *                                                                       $columns = array(
45
     *                                                                       column_id => array(
46
     *                                                                       'title' => Column heading,
47
     *                                                                       'class' => The class to apply on the column cells,
48
     *                                                                       'field' => Field name for $tabledata->fields[...],
49
     *                                                                       'help'  => Help page for this column,
50
     *                                                                       ), ...
51
     *                                                                       );
52
     * @param array                                               $actions   Actions that can be performed on each object:
53
     *                                                                       $actions = array(
54
     *                                                                       * multi action support
55
     *                                                                       * parameters are serialized for each entries and given in $_REQUEST['ma']
56
     *                                                                       'multiactions' => array(
57
     *                                                                       'keycols' => Associative array of (URL variable => field name), // fields included in the form
58
     *                                                                       'url' => URL submission,
59
     *                                                                       'default' => Default selected action in the form. If null, an empty action is added & selected
60
     *                                                                       ),
61
     *                                                                       * actions *
62
     *                                                                       action_id => array(
63
     *                                                                       'title' => Action heading,
64
     *                                                                       'url'   => Static part of URL.  Often we rely
65
     *                                                                       relative urls, usually the page itself (not '' !), or just a query string,
66
     *                                                                       'vars'  => Associative array of (URL variable => field name),
67
     *                                                                       'multiaction' => Name of the action to execute.
68
     *                                                                       Add this action to the multi action form
69
     *                                                                       ), ...
70
     *                                                                       );
71
     * @param string                                              $place     Place where the $actions are displayed. Like 'display-browse',  where 'display'
72
     *                                                                       is the entrypoint (/src/views/display) and 'browse' is the action used inside its controller (in this case, doBrowse).
73
     * @param string                                              $nodata    (optional) Message to display if data set is empty
74
     * @param callable                                            $pre_fn    (optional) callback closure for each row. It will be passed two params: $rowdata and $actions,
75
     *                                                                       it may be used to derive new fields or modify actions.
76
     *                                                                       It can return an array of actions specific to the row,  or if nothing is returned then the standard actions are used.
77
     *                                                                       (see TblpropertiesController and ConstraintsController for examples)
78
     *                                                                       The function must not must not store urls because     they are relative and won't work out of context.
79
     */
80
    public function initialize(&$tabledata, &$columns, &$actions, $place, $nodata = '', $pre_fn = null): void
81
    {
82
        // Action buttons hook's place
83
        $this->plugin_functions_parameters = [
84
            'actionbuttons' => &$actions,
85
            'place'         => $place,
86
        ];
87
88
        if ($this->has_ma = isset($actions['multiactions'])) {
89
            $this->ma = $actions['multiactions'];
90
        }
91
        unset($actions['multiactions']);
92
93
        $this->tabledata = $tabledata;
94
        $this->columns   = $columns;
95
        $this->actions   = $actions;
96
        $this->place     = $place;
97
        $this->nodata    = $nodata;
98
        $this->pre_fn    = $pre_fn;
99
    }
100
101
    public function printTable($turn_into_datatable = true, $with_body = true)
102
    {
103
        if (0 >= $this->tabledata->recordCount()) {
104
            return "<p>{$this->nodata}</p>" . \PHP_EOL;
105
        }
106
107
        $tablehtml = '';
108
        // Remove the 'comment' column if they have been disabled
109
        if (!$this->conf['show_comments']) {
110
            unset($this->columns['comment']);
111
        }
112
113
        if (isset($this->columns['comment'])) {
114
            // Uncomment this for clipped comments.
115
            // TODO: This should be a user option.
116
            //$columns['comment']['params']['clip'] = true;
117
        }
118
119
        list($matop_html, $mabottom_html) = $this->_getMaHtml();
120
121
        $tablehtml .= $matop_html;
122
123
        $tablehtml .= '<table width="auto" class="' . ($turn_into_datatable ? 'will_be_datatable ' : ' ') . $this->place . '">' . \PHP_EOL;
124
125
        $tablehtml .= $this->getThead();
126
127
        //$this->prtrace($tabledata, $actions);
128
129
        $tablehtml .= $with_body ? $this->getTbody() : '';
130
131
        $tablehtml .= $this->getTfooter();
132
133
        $tablehtml .= '</table>' . \PHP_EOL;
134
135
        // Multi action table footer w/ options & [un]check'em all
136
        $tablehtml .= $mabottom_html;
137
138
        return $tablehtml;
139
    }
140
141
    public function getThead()
142
    {
143
        $columns = $this->columns;
144
        $actions = $this->actions;
145
146
        $thead_html = '<thead><tr>' . \PHP_EOL;
147
148
        // Display column headings
149
        if ($this->has_ma) {
150
            $thead_html .= '<th></th>';
151
        }
152
153
        foreach ($columns as $column_id => $column) {
154
            // Handle cases where no class has been passed
155
156
            $class = (isset($column['class']) && '' !== $column['class']) ? $column['class'] : '';
157
158
            switch ($column_id) {
159
                case 'actions':
160
                    if (0 < \count($actions)) {
161
                        $thead_html .= '<th class="data" >' . $column['title'] . '</th>' . \PHP_EOL;
162
                    }
163
164
                    break;
165
                default:
166
                    $thead_html .= '<th class="data' . $class . '">';
167
168
                    if (isset($column['help'])) {
169
                        $thead_html .= $this->misc->printHelp($column['title'], $column['help'], false);
170
                    } else {
171
                        $thead_html .= $column['title'];
172
                    }
173
174
                    $thead_html .= '</th>' . \PHP_EOL;
175
176
                    break;
177
            }
178
        }
179
        $thead_html .= '</tr></thead>' . \PHP_EOL;
180
181
        return $thead_html;
182
    }
183
184
    public function getTfooter()
185
    {
186
        $columns = $this->columns;
187
        $actions = $this->actions;
188
189
        $tfoot_html = '<tfoot><tr>' . \PHP_EOL;
190
191
        // Display column headings
192
        if ($this->has_ma) {
193
            $tfoot_html .= '<td></td>';
194
        }
195
196
        foreach ($columns as $column_id => $column) {
197
            // Handle cases where no class has been passed
198
199
            $class = (isset($column['class']) && '' !== $column['class']) ? $column['class'] : '';
200
201
            if ('actions' !== $column_id || 0 < \count($actions)) {
202
                $tfoot_html .= "<td class=\"data{$class}\"></td>" . \PHP_EOL;
203
            }
204
        }
205
        $tfoot_html .= '</tr></tfoot>' . \PHP_EOL;
206
207
        return $tfoot_html;
208
    }
209
210
    private function _getMaHtml()
211
    {
212
        $matop_html    = '';
213
        $ma_bottomhtml = '';
214
        $lang          = $this->lang;
215
216
        if ($this->has_ma) {
217
            $matop_html .= '<script src="' . SUBFOLDER . '/assets/js/multiactionform.js" type="text/javascript"></script>' . \PHP_EOL;
218
            $matop_html .= \sprintf('<form id="multi_form" action="%s" method="post" enctype="multipart/form-data">%s', $this->ma['url'], \PHP_EOL);
219
            $this->coalesceArr($this->ma, 'vars', []);
220
221
            foreach ($this->ma['vars'] as $k => $v) {
222
                $matop_html .= \sprintf('<input type="hidden" name="%s" value="%s" />', $k, $v);
223
            }
224
225
            // if default is not set or doesn't exist, set it to null
226
            if (!isset($this->ma['default']) || !isset($this->actions[$this->ma['default']])) {
227
                $this->ma['default'] = null;
228
            }
229
230
            $ma_bottomhtml .= '<br />' . \PHP_EOL;
231
            $ma_bottomhtml .= '<table>' . \PHP_EOL;
232
            $ma_bottomhtml .= '<tr>' . \PHP_EOL;
233
            $ma_bottomhtml .= "<th class=\"data\" style=\"text-align: left\" colspan=\"3\">{$lang['stractionsonmultiplelines']}</th>" . \PHP_EOL;
234
            $ma_bottomhtml .= '</tr>' . \PHP_EOL;
235
            $ma_bottomhtml .= '<tr class="row1">' . \PHP_EOL;
236
            $ma_bottomhtml .= '<td>';
237
            $ma_bottomhtml .= "<a href=\"#\" onclick=\"javascript:checkAll(true);\">{$lang['strselectall']}</a> / ";
238
            $ma_bottomhtml .= "<a href=\"#\" onclick=\"javascript:checkAll(false);\">{$lang['strunselectall']}</a></td>" . \PHP_EOL;
239
            $ma_bottomhtml .= '<td>&nbsp;--->&nbsp;</td>' . \PHP_EOL;
240
            $ma_bottomhtml .= '<td>' . \PHP_EOL;
241
            $ma_bottomhtml .= "\t<select name=\"action\">" . \PHP_EOL;
242
243
            if (null === $this->ma['default']) {
244
                $ma_bottomhtml .= "\t\t<option value=\"\">--</option>" . \PHP_EOL;
245
            }
246
247
            foreach ($this->actions as $k => $a) {
248
                if (isset($a['multiaction'])) {
249
                    $selected = $this->ma['default'] === $k ? ' selected="selected" ' : '';
250
                    $ma_bottomhtml .= "\t\t";
251
                    $ma_bottomhtml .= '<option value="' . $a['multiaction'] . '" ' . $selected . ' rel="' . $k . '">' . $a['content'] . '</option>';
252
                    $ma_bottomhtml .= \PHP_EOL;
253
                }
254
            }
255
256
            $ma_bottomhtml .= "\t</select>" . \PHP_EOL;
257
            $ma_bottomhtml .= "<input type=\"submit\" value=\"{$lang['strexecute']}\" />" . \PHP_EOL;
258
            $ma_bottomhtml .= $this->getForm();
259
            $ma_bottomhtml .= '</td>' . \PHP_EOL;
260
            $ma_bottomhtml .= '</tr>' . \PHP_EOL;
261
            $ma_bottomhtml .= '</table>' . \PHP_EOL;
262
            $ma_bottomhtml .= '</form>';
263
        }
264
265
        return [$matop_html, $ma_bottomhtml];
266
    }
267
268
    private function getTbody()
269
    {
270
        $columns   = $this->columns;
271
        $actions   = $this->actions;
272
        $tabledata = $this->tabledata;
273
        $pre_fn    = $this->pre_fn;
274
275
        // Display table rows
276
        $i          = 0;
277
        $tbody_html = '<tbody>';
278
279
        while (!$tabledata->EOF) {
280
            $id = ($i % 2) + 1;
281
282
            unset($alt_actions);
283
284
            if (null !== $pre_fn) {
285
                $alt_actions = $pre_fn($tabledata, $actions);
286
            }
287
288
            if (!isset($alt_actions)) {
289
                $alt_actions = &$actions;
290
            }
291
292
            $tbody_html .= \sprintf('<tr class="data%s">', $id) . \PHP_EOL;
293
294
            if ($this->has_ma) {
295
                $a = [];
296
297
                foreach ($this->ma['keycols'] as $k => $v) {
298
                    $a[$k] = $tabledata->fields[$v];
299
                }
300
                //\Kint::dump($a);
301
                $tbody_html .= \sprintf('<td><input type="checkbox" name="ma[]" value="%s"/></td>', \htmlentities(\serialize($a), \ENT_COMPAT, 'UTF-8')) . \PHP_EOL;
302
            }
303
304
            foreach ($columns as $column_id => $column) {
305
                // Apply default values for missing parameters
306
                if (isset($column['url']) && !isset($column['vars'])) {
307
                    $column['vars'] = [];
308
                }
309
                $class = (isset($column['class']) && '' !== $column['class']) ? $column['class'] : '';
310
311
                switch ($column_id) {
312
                    case 'actions':
313
                        $tbody_html .= "<td class=\"opbutton{$id} {$class}\">";
314
315
                        foreach ($alt_actions as $action) {
316
                            if (isset($action['disable']) && true === $action['disable']) {
317
                                continue;
318
                            }
319
                            $action['fields'] = $tabledata->fields;
320
                            $tbody_html .= $this->printLink($action, false, __METHOD__);
321
                        }
322
                        $tbody_html .= '</td>' . \PHP_EOL;
323
324
                        break;
325
                    case 'comment':
326
                        $tbody_html .= "<td class='comment_cell'>";
327
                        $tbody_html .= \htmlentities(Decorator::get_sanitized_value($column['field'], $tabledata->fields));
328
                        $tbody_html .= '</td>';
329
330
                        break;
331
                    default:
332
                        $tbody_html .= '<td class="' . $class . '">';
333
                        $val = Decorator::get_sanitized_value($column['field'], $tabledata->fields);
334
335
                        if (null !== $val) {
336
                            if (isset($column['url'])) {
337
                                $tbody_html .= "<a href=\"{$column['url']}";
338
                                $tbody_html .= $this->printUrlVars($column['vars'], $tabledata->fields, false);
339
                                $tbody_html .= '">';
340
                            }
341
                            $type   = $column['type'] ?? null;
342
                            $params = $column['params'] ?? [];
343
                            $tbody_html .= $this->misc->printVal($val, $type, $params);
344
345
                            if (isset($column['url'])) {
346
                                $tbody_html .= '</a>';
347
                            }
348
                        }
349
350
                        $tbody_html .= '</td>' . \PHP_EOL;
351
352
                        break;
353
                }
354
            }
355
            $tbody_html .= '</tr>' . \PHP_EOL;
356
357
            $tabledata->moveNext();
358
            ++$i;
359
        }
360
361
        $tbody_html .= '</tbody>';
362
363
        return $tbody_html;
364
    }
365
366
    private function getForm()
367
    {
368
        if (!$this->form) {
369
            $this->form = $this->misc->setForm();
370
        }
371
372
        return $this->form;
373
    }
374
375
    private function printUrlVars(&$vars, &$fields, bool $do_print = true)
376
    {
377
        $url_vars_html = '';
378
379
        foreach ($vars as $var => $varfield) {
380
            $url_vars_html .= "{$var}=" . \urlencode($fields[$varfield]) . '&amp;';
381
        }
382
383
        if ($do_print) {
384
            echo $url_vars_html;
385
        } else {
386
            return $url_vars_html;
387
        }
388
    }
389
}
390