Passed
Push — develop ( c2019a...2cab77 )
by Felipe
04:50
created

HTMLTableController::getThead()   C

Complexity

Conditions 8
Paths 34

Size

Total Lines 40
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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