Passed
Push — develop ( 442876...34732b )
by Felipe
46s
created

ViewsController::render()   C

Complexity

Conditions 17
Paths 17

Size

Total Lines 79
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 55
nc 17
nop 0
dl 0
loc 79
rs 5.083
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
/*
4
 * PHPPgAdmin v6.0.0-beta.30
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Base controller class.
13
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
14
class ViewsController extends BaseController
15
{
16
    public $script          = 'views.php';
17
    public $controller_name = 'ViewsController';
18
    public $table_place     = 'views-views';
19
20
    /**
21
     * Default method to render the controller according to the action parameter.
22
     */
23
    public function render()
24
    {
25
        $lang   = $this->lang;
26
        $action = $this->action;
27
28
        if ('tree' == $action) {
29
            return $this->doTree();
30
        }
31
        if ('subtree' == $action) {
32
            return $this->doSubTree();
33
        }
34
35
        $this->printHeader($lang['strviews']);
36
        $this->printBody();
37
38
        switch ($action) {
39
            case 'selectrows':
40
                if (!isset($_REQUEST['cancel'])) {
41
                    $this->doSelectRows(false);
42
                } else {
43
                    $this->doDefault();
44
                }
45
46
                break;
47
            case 'confselectrows':
48
                $this->doSelectRows(true);
49
50
                break;
51
            case 'save_create_wiz':
52
                if (isset($_REQUEST['cancel'])) {
53
                    $this->doDefault();
54
                } else {
55
                    $this->doSaveCreateWiz();
56
                }
57
58
                break;
59
            case 'wiz_create':
60
                $this->doWizardCreate();
61
62
                break;
63
            case 'set_params_create':
64
                if (isset($_POST['cancel'])) {
65
                    $this->doDefault();
66
                } else {
67
                    $this->doSetParamsCreate();
68
                }
69
70
                break;
71
            case 'save_create':
72
                if (isset($_REQUEST['cancel'])) {
73
                    $this->doDefault();
74
                } else {
75
                    $this->doSaveCreate();
76
                }
77
78
                break;
79
            case 'create':
80
                $this->doCreate();
81
82
                break;
83
            case 'drop':
84
                if (isset($_POST['drop'])) {
85
                    $this->doDrop(false);
86
                } else {
87
                    $this->doDefault();
88
                }
89
90
                break;
91
            case 'confirm_drop':
92
                $this->doDrop(true);
93
94
                break;
95
            default:
96
                $this->doDefault();
97
98
                break;
99
        }
100
101
        return $this->printFooter();
102
    }
103
104
    /**
105
     * Show default list of views in the database.
106
     *
107
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
108
     */
109
    public function doDefault($msg = '')
110
    {
111
        $lang = $this->lang;
112
        $data = $this->misc->getDatabaseAccessor();
113
114
        $this->printTrail('schema');
115
        $this->printTabs('schema', 'views');
116
        $this->printMsg($msg);
117
118
        $views = $data->getViews();
119
120
        $columns = [
121
            'view'    => [
122
                'title' => $lang['strview'],
123
                'field' => Decorator::field('relname'),
124
                'url'   => \SUBFOLDER . "/redirect/view?{$this->misc->href}&amp;",
125
                'vars'  => ['view' => 'relname'],
126
            ],
127
            'owner'   => [
128
                'title' => $lang['strowner'],
129
                'field' => Decorator::field('relowner'),
130
            ],
131
            'actions' => [
132
                'title' => $lang['stractions'],
133
            ],
134
            'comment' => [
135
                'title' => $lang['strcomment'],
136
                'field' => Decorator::field('relcomment'),
137
            ],
138
        ];
139
140
        $actions = [
141
            'multiactions' => [
142
                'keycols' => ['view' => 'relname'],
143
                'url'     => 'views.php',
144
            ],
145
            'browse'       => [
146
                'content' => $lang['strbrowse'],
147
                'attr'    => [
148
                    'href' => [
149
                        'url'     => 'display.php',
150
                        'urlvars' => [
151
                            'action'  => 'confselectrows',
152
                            'subject' => 'view',
153
                            'return'  => 'schema',
154
                            'view'    => Decorator::field('relname'),
155
                        ],
156
                    ],
157
                ],
158
            ],
159
            'select'       => [
160
                'content' => $lang['strselect'],
161
                'attr'    => [
162
                    'href' => [
163
                        'url'     => 'views.php',
164
                        'urlvars' => [
165
                            'action' => 'confselectrows',
166
                            'view'   => Decorator::field('relname'),
167
                        ],
168
                    ],
169
                ],
170
            ],
171
172
            // Insert is possible if the relevant rule for the view has been created.
173
            //            'insert' => array(
174
            //                'title'    => $lang['strinsert'],
175
            //                'url'    => "views.php?action=confinsertrow&amp;{$this->misc->href}&amp;",
176
            //                'vars'    => array('view' => 'relname'),
177
            //            ),
178
179
            'alter'        => [
180
                'content' => $lang['stralter'],
181
                'attr'    => [
182
                    'href' => [
183
                        'url'     => 'viewproperties.php',
184
                        'urlvars' => [
185
                            'action' => 'confirm_alter',
186
                            'view'   => Decorator::field('relname'),
187
                        ],
188
                    ],
189
                ],
190
            ],
191
            'drop'         => [
192
                'multiaction' => 'confirm_drop',
193
                'content'     => $lang['strdrop'],
194
                'attr'        => [
195
                    'href' => [
196
                        'url'     => 'views.php',
197
                        'urlvars' => [
198
                            'action' => 'confirm_drop',
199
                            'view'   => Decorator::field('relname'),
200
                        ],
201
                    ],
202
                ],
203
            ],
204
        ];
205
206
        echo $this->printTable($views, $columns, $actions, $this->table_place, $lang['strnoviews']);
207
208
        $navlinks = [
209
            'create'    => [
210
                'attr'    => [
211
                    'href' => [
212
                        'url'     => 'views.php',
213
                        'urlvars' => [
214
                            'action'   => 'create',
215
                            'server'   => $_REQUEST['server'],
216
                            'database' => $_REQUEST['database'],
217
                            'schema'   => $_REQUEST['schema'],
218
                        ],
219
                    ],
220
                ],
221
                'content' => $lang['strcreateview'],
222
            ],
223
            'createwiz' => [
224
                'attr'    => [
225
                    'href' => [
226
                        'url'     => 'views.php',
227
                        'urlvars' => [
228
                            'action'   => 'wiz_create',
229
                            'server'   => $_REQUEST['server'],
230
                            'database' => $_REQUEST['database'],
231
                            'schema'   => $_REQUEST['schema'],
232
                        ],
233
                    ],
234
                ],
235
                'content' => $lang['strcreateviewwiz'],
236
            ],
237
        ];
238
        $this->printNavLinks($navlinks, $this->table_place, get_defined_vars());
239
    }
240
241
    /**
242
     * Generate XML for the browser tree.
243
     */
244
    public function doTree()
245
    {
246
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
247
        $data = $this->misc->getDatabaseAccessor();
248
249
        $views = $data->getViews();
250
251
        $reqvars = $this->misc->getRequestVars('view');
252
253
        $attrs = [
254
            'text'       => Decorator::field('relname'),
255
            'icon'       => 'View',
256
            'iconAction' => Decorator::url('display.php', $reqvars, ['view' => Decorator::field('relname')]),
257
            'toolTip'    => Decorator::field('relcomment'),
258
            'action'     => Decorator::redirecturl('redirect.php', $reqvars, ['view' => Decorator::field('relname')]),
259
            'branch'     => Decorator::url('views.php', $reqvars, ['action' => 'subtree', 'view' => Decorator::field('relname')]),
260
        ];
261
262
        return $this->printTree($views, $attrs, 'views');
263
    }
264
265
    public function doSubTree()
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
266
    {
267
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
268
        $data = $this->misc->getDatabaseAccessor();
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
269
270
        $tabs    = $this->misc->getNavTabs('view');
271
        $items   = $this->adjustTabsForTree($tabs);
272
        $reqvars = $this->misc->getRequestVars('view');
273
274
        $attrs = [
275
            'text'   => Decorator::field('title'),
276
            'icon'   => Decorator::field('icon'),
277
            'action' => Decorator::actionurl(Decorator::field('url'), $reqvars, Decorator::field('urlvars'), ['view' => $_REQUEST['view']]),
278
            'branch' => Decorator::ifempty(
279
                Decorator::field('branch'),
280
                '',
281
                Decorator::url(
282
                    Decorator::field('url'),
283
                    Decorator::field('urlvars'),
284
                    $reqvars,
285
                    [
286
                        'action' => 'tree',
287
                        'view'   => $_REQUEST['view'],
288
                    ]
289
                )
290
            ),
291
        ];
292
293
        return $this->printTree($items, $attrs, 'view');
294
    }
295
296
    /**
297
     * Ask for select parameters and perform select.
298
     *
299
     * @param mixed $confirm
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
300
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
301
     */
302
    public function doSelectRows($confirm, $msg = '')
303
    {
304
        $lang = $this->lang;
305
        $data = $this->misc->getDatabaseAccessor();
306
307
        if ($confirm) {
308
            $this->printTrail('view');
309
            $this->printTabs('view', 'select');
310
            $this->printMsg($msg);
311
312
            $attrs = $data->getTableAttributes($_REQUEST['view']);
313
314
            echo '<form action="' . \SUBFOLDER . '/src/views/' . $this->script . '" method="post" id="selectform">';
315
            echo "\n";
316
317
            if ($attrs->recordCount() > 0) {
318
                // JavaScript for select all feature
319
                echo "<script type=\"text/javascript\">\n";
320
                echo "//<![CDATA[\n";
321
                echo "	function selectAll() {\n";
322
                echo "		for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n";
323
                echo "			var e = document.getElementById('selectform').elements[i];\n";
324
                echo "			if (e.name.indexOf('show') == 0) { \n ";
325
                echo "				e.checked = document.getElementById('selectform').selectall.checked;\n";
326
                echo "			}\n";
327
                echo "		}\n";
328
                echo "	}\n";
329
                echo "//]]>\n";
330
                echo "</script>\n";
331
332
                echo "<table>\n";
333
334
                // Output table header
335
                echo "<tr><th class=\"data\">{$lang['strshow']}</th><th class=\"data\">{$lang['strcolumn']}</th>";
336
                echo "<th class=\"data\">{$lang['strtype']}</th><th class=\"data\">{$lang['stroperator']}</th>";
337
                echo "<th class=\"data\">{$lang['strvalue']}</th></tr>";
338
339
                $i = 0;
340
                while (!$attrs->EOF) {
341
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
342
                    // Set up default value if there isn't one already
343
                    if (!isset($_REQUEST['values'][$attrs->fields['attname']])) {
344
                        $_REQUEST['values'][$attrs->fields['attname']] = null;
345
                    }
346
347
                    if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) {
348
                        $_REQUEST['ops'][$attrs->fields['attname']] = null;
349
                    }
350
351
                    // Continue drawing row
352
                    $id = (0 == ($i % 2) ? '1' : '2');
353
                    echo "<tr class=\"data{$id}\">\n";
354
                    echo '<td style="white-space:nowrap;">';
355
                    echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"',
356
                    isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>';
357
                    echo '<td style="white-space:nowrap;">', $this->misc->printVal($attrs->fields['attname']), '</td>';
358
                    echo '<td style="white-space:nowrap;">', $this->misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>';
359
                    echo '<td style="white-space:nowrap;">';
360
                    echo "<select name=\"ops[{$attrs->fields['attname']}]\">\n";
361
                    foreach (array_keys($data->selectOps) as $v) {
362
                        echo '<option value="', htmlspecialchars($v), '"', ($_REQUEST['ops'][$attrs->fields['attname']] == $v) ? ' selected="selected"' : '',
363
                        '>', htmlspecialchars($v), "</option>\n";
364
                    }
365
                    echo "</select></td>\n";
366
                    echo '<td style="white-space:nowrap;">', $data->printField(
367
                        "values[{$attrs->fields['attname']}]",
368
                        $_REQUEST['values'][$attrs->fields['attname']],
369
                        $attrs->fields['type']
370
                    ), '</td>';
371
                    echo "</tr>\n";
372
                    ++$i;
373
                    $attrs->moveNext();
374
                }
375
                // Select all checkbox
376
                echo "<tr><td colspan=\"5\"><input type=\"checkbox\" id=\"selectall\" name=\"selectall\" accesskey=\"a\" onclick=\"javascript:selectAll()\" /><label for=\"selectall\">{$lang['strselectallfields']}</label></td></tr>";
377
                echo "</table>\n";
378
            } else {
379
                echo "<p>{$lang['strinvalidparam']}</p>\n";
380
            }
381
382
            echo "<p><input type=\"hidden\" name=\"action\" value=\"selectrows\" />\n";
383
            echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['view']), "\" />\n";
384
            echo "<input type=\"hidden\" name=\"subject\" value=\"view\" />\n";
385
            echo $this->misc->form;
386
            echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$lang['strselect']}\" />\n";
387
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
388
            echo "</form>\n";
389
390
            return;
391
        }
392
        if (!isset($_POST['show'])) {
393
            $_POST['show'] = [];
394
        }
395
396
        if (!isset($_POST['values'])) {
397
            $_POST['values'] = [];
398
        }
399
400
        if (!isset($_POST['nulls'])) {
401
            $_POST['nulls'] = [];
402
        }
403
404
        // Verify that they haven't supplied a value for unary operators
405
        foreach ($_POST['ops'] as $k => $v) {
406
            if ('p' == $data->selectOps[$v] && $_POST['values'][$k] != '') {
407
                $this->doSelectRows(true, $lang['strselectunary']);
408
409
                return;
410
            }
411
        }
412
413
        if (0 == sizeof($_POST['show'])) {
414
            return $this->doSelectRows(true, $lang['strselectneedscol']);
415
        }
416
        // Generate query SQL
417
        $query = $data->getSelectSQL($_REQUEST['view'], array_keys($_POST['show']), $_POST['values'], $_POST['ops']);
418
419
        $_REQUEST['query']  = $query;
420
        $_REQUEST['return'] = 'schema';
421
422
        $this->setNoOutput(true);
423
424
        $display_controller = new DisplayController($this->getContainer());
425
426
        return $display_controller->render();
427
    }
428
429
    /**
430
     * Show confirmation of drop and perform actual drop.
431
     *
432
     * @param mixed $confirm
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
433
     */
434
    public function doDrop($confirm)
435
    {
436
        $lang = $this->lang;
437
        $data = $this->misc->getDatabaseAccessor();
438
439
        if (empty($_REQUEST['view']) && empty($_REQUEST['ma'])) {
440
            return $this->doDefault($lang['strspecifyviewtodrop']);
441
        }
442
443
        if ($confirm) {
444
            $this->printTrail('view');
445
            $this->printTitle($lang['strdrop'], 'pg.view.drop');
446
447
            echo '<form action="' . \SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
448
449
            //If multi drop
450
            if (isset($_REQUEST['ma'])) {
451
                foreach ($_REQUEST['ma'] as $v) {
452
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
453
                    echo '<p>', sprintf($lang['strconfdropview'], $this->misc->printVal($a['view'])), "</p>\n";
454
                    echo '<input type="hidden" name="view[]" value="', htmlspecialchars($a['view']), "\" />\n";
455
                }
456
            } else {
457
                echo '<p>', sprintf($lang['strconfdropview'], $this->misc->printVal($_REQUEST['view'])), "</p>\n";
458
                echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['view']), "\" />\n";
459
            }
460
461
            echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
462
463
            echo $this->misc->form;
464
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
465
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
466
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
467
            echo "</form>\n";
468
        } else {
469
            if (is_array($_POST['view'])) {
470
                $msg    = '';
471
                $status = $data->beginTransaction();
472
                if (0 == $status) {
473
                    foreach ($_POST['view'] as $s) {
474
                        $status = $data->dropView($s, isset($_POST['cascade']));
475
                        if (0 == $status) {
476
                            $msg .= sprintf('%s: %s<br />', htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdropped']);
477
                        } else {
478
                            $data->endTransaction();
479
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdroppedbad']));
480
481
                            return;
482
                        }
483
                    }
484
                }
485
                if (0 == $data->endTransaction()) {
486
                    // Everything went fine, back to the Default page....
487
                    $this->misc->setReloadBrowser(true);
488
                    $this->doDefault($msg);
489
                } else {
490
                    $this->doDefault($lang['strviewdroppedbad']);
491
                }
492
            } else {
493
                $status = $data->dropView($_POST['view'], isset($_POST['cascade']));
494
                if (0 == $status) {
495
                    $this->misc->setReloadBrowser(true);
496
                    $this->doDefault($lang['strviewdropped']);
497
                } else {
498
                    $this->doDefault($lang['strviewdroppedbad']);
499
                }
500
            }
501
        }
502
    }
503
504
    /**
505
     * Sets up choices for table linkage, and which fields to select for the view we're creating.
506
     *
507
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
508
     */
509
    public function doSetParamsCreate($msg = '')
510
    {
511
        $lang = $this->lang;
512
        $data = $this->misc->getDatabaseAccessor();
513
514
        // Check that they've chosen tables for the view definition
515
        if (!isset($_POST['formTables'])) {
516
            $this->doWizardCreate($lang['strviewneedsdef']);
517
        } else {
518
            // Initialise variables
519
            if (!isset($_REQUEST['formView'])) {
520
                $_REQUEST['formView'] = '';
521
            }
522
523
            if (!isset($_REQUEST['formComment'])) {
524
                $_REQUEST['formComment'] = '';
525
            }
526
527
            $this->printTrail('schema');
528
            $this->printTitle($lang['strcreateviewwiz'], 'pg.view.create');
529
            $this->printMsg($msg);
530
531
            $tblCount = sizeof($_POST['formTables']);
532
            //unserialize our schema/table information and store in arrSelTables
533
            for ($i = 0; $i < $tblCount; ++$i) {
534
                $arrSelTables[] = unserialize($_POST['formTables'][$i]);
535
            }
536
537
            $linkCount = $tblCount;
0 ignored issues
show
Unused Code introduced by
The assignment to $linkCount is dead and can be removed.
Loading history...
538
539
            //get linking keys
540
            $rsLinkKeys = $data->getLinkingKeys($arrSelTables);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $arrSelTables does not seem to be defined for all execution paths leading up to this point.
Loading history...
541
            $linkCount  = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
542
543
            $arrFields = []; //array that will hold all our table/field names
544
545
            //if we have schemas we need to specify the correct schema for each table we're retrieiving
546
            //with getTableAttributes
547
            $curSchema = $data->_schema;
548
            for ($i = 0; $i < $tblCount; ++$i) {
549
                if ($arrSelTables[$i]['schemaname'] != $data->_schema) {
550
                    $data->setSchema($arrSelTables[$i]['schemaname']);
551
                }
552
553
                $attrs = $data->getTableAttributes($arrSelTables[$i]['tablename']);
554
                while (!$attrs->EOF) {
555
                    $arrFields["{$arrSelTables[$i]['schemaname']}.{$arrSelTables[$i]['tablename']}.{$attrs->fields['attname']}"] = serialize(
556
                        [
557
                            'schemaname' => $arrSelTables[$i]['schemaname'],
558
                            'tablename'  => $arrSelTables[$i]['tablename'],
559
                            'fieldname'  => $attrs->fields['attname']]
560
                    );
561
                    $attrs->moveNext();
562
                }
563
564
                $data->setSchema($curSchema);
565
            }
566
            asort($arrFields);
567
568
            echo '<form action="' . \SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
569
            echo "<table>\n";
570
            echo "<tr><th class=\"data\">{$lang['strviewname']}</th></tr>";
571
            echo "<tr>\n<td class=\"data1\">\n";
572
            // View name
573
            echo '<input name="formView" value="', htmlspecialchars($_REQUEST['formView']), "\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />\n";
574
            echo "</td>\n</tr>\n";
575
            echo "<tr><th class=\"data\">{$lang['strcomment']}</th></tr>";
576
            echo "<tr>\n<td class=\"data1\">\n";
577
            // View comments
578
            echo '<textarea name="formComment" rows="3" cols="32">',
579
            htmlspecialchars($_REQUEST['formComment']), "</textarea>\n";
580
            echo "</td>\n</tr>\n";
581
            echo "</table>\n";
582
583
            // Output selector for fields to be retrieved from view
584
            echo "<table>\n";
585
            echo "<tr><th class=\"data\">{$lang['strcolumns']}</th></tr>";
586
            echo "<tr>\n<td class=\"data1\">\n";
587
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, 'formFields[]', false, '', true);
588
            echo "</td>\n</tr>";
589
            echo "<tr><td><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth1\" value=\"rename\" /><label for=\"dblFldMeth1\">{$lang['strrenamedupfields']}</label>";
590
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth2\" value=\"drop\" /><label for=\"dblFldMeth2\">{$lang['strdropdupfields']}</label>";
591
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth3\" value=\"\" checked=\"checked\" /><label for=\"dblFldMeth3\">{$lang['strerrordupfields']}</label></td></tr></table><br />";
592
593
            // Output the Linking keys combo boxes
594
            echo "<table>\n";
595
            echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";
596
            $rowClass = 'data1';
597
            for ($i = 0; $i < $linkCount; ++$i) {
598
                // Initialise variables
599
                if (!isset($formLink[$i]['operator'])) {
600
                    $formLink[$i]['operator'] = 'INNER JOIN';
601
                }
602
603
                echo "<tr>\n<td class=\"${rowClass}\">\n";
604
605
                if (!$rsLinkKeys->EOF) {
606
                    $curLeftLink  = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['p_schema'], 'tablename' => $rsLinkKeys->fields['p_table'], 'fieldname' => $rsLinkKeys->fields['p_field']]));
607
                    $curRightLink = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['f_schema'], 'tablename' => $rsLinkKeys->fields['f_table'], 'fieldname' => $rsLinkKeys->fields['f_field']]));
608
                    $rsLinkKeys->moveNext();
609
                } else {
610
                    $curLeftLink  = '';
611
                    $curRightLink = '';
612
                }
613
614
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[${i}][leftlink]", true, $curLeftLink, false);
615
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($data->joinOps, "formLink[${i}][operator]", true, $formLink[$i]['operator']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $formLink does not seem to be defined for all execution paths leading up to this point.
Loading history...
616
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[${i}][rightlink]", true, $curRightLink, false);
617
                echo "</td>\n</tr>\n";
618
                $rowClass = 'data1' == $rowClass ? 'data2' : 'data1';
619
            }
620
            echo "</table>\n<br />\n";
621
622
            // Build list of available operators (infix only)
623
            $arrOperators = [];
624
            foreach ($data->selectOps as $k => $v) {
625
                if ('i' == $v) {
626
                    $arrOperators[$k] = $k;
627
                }
628
            }
629
630
            // Output additional conditions, note that this portion of the wizard treats the right hand side as literal values
631
            //(not as database objects) so field names will be treated as strings, use the above linking keys section to perform joins
632
            echo "<table>\n";
633
            echo "<tr><th class=\"data\">{$lang['strviewconditions']}</th></tr>";
634
            $rowClass = 'data1';
635
            for ($i = 0; $i < $linkCount; ++$i) {
636
                echo "<tr>\n<td class=\"${rowClass}\">\n";
637
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formCondition[${i}][field]");
638
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrOperators, "formCondition[${i}][operator]", false, false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $szDefault of PHPPgAdmin\XHtml\HTMLController::printCombo(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

638
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrOperators, "formCondition[${i}][operator]", false, /** @scrutinizer ignore-type */ false);
Loading history...
639
                echo "<input type=\"text\" name=\"formCondition[${i}][txt]\" />\n";
640
                echo "</td>\n</tr>\n";
641
                $rowClass = 'data1' == $rowClass ? 'data2' : 'data1';
642
            }
643
            echo "</table>\n";
644
            echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create_wiz\" />\n";
645
646
            foreach ($arrSelTables as $curTable) {
647
                echo '<input type="hidden" name="formTables[]" value="' . htmlspecialchars(serialize($curTable)) . "\" />\n";
648
            }
649
650
            echo $this->misc->form;
651
            echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
652
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
653
            echo "</form>\n";
654
        }
655
    }
656
657
    /**
658
     * Display a wizard where they can enter a new view.
659
     *
660
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
661
     */
662
    public function doWizardCreate($msg = '')
663
    {
664
        $lang = $this->lang;
665
        $data = $this->misc->getDatabaseAccessor();
666
667
        $tables = $data->getTables(true);
668
669
        $this->printTrail('schema');
670
        $this->printTitle($lang['strcreateviewwiz'], 'pg.view.create');
671
        $this->printMsg($msg);
672
673
        echo '<form action="' . \SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
674
        echo "<table>\n";
675
        echo "<tr><th class=\"data\">{$lang['strtables']}</th></tr>";
676
        echo "<tr>\n<td class=\"data1\">\n";
677
678
        $arrTables = [];
679
        while (!$tables->EOF) {
680
            $arrTmp                                                                   = [];
681
            $arrTmp['schemaname']                                                     = $tables->fields['nspname'];
682
            $arrTmp['tablename']                                                      = $tables->fields['relname'];
683
            $arrTables[$tables->fields['nspname'] . '.' . $tables->fields['relname']] = serialize($arrTmp);
684
            $tables->moveNext();
685
        }
686
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrTables, 'formTables[]', false, '', true);
687
688
        echo "</td>\n</tr>\n";
689
        echo "</table>\n";
690
        echo "<p><input type=\"hidden\" name=\"action\" value=\"set_params_create\" />\n";
691
        echo $this->misc->form;
692
        echo "<input type=\"submit\" value=\"{$lang['strnext']}\" />\n";
693
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
694
        echo "</form>\n";
695
    }
696
697
    /**
698
     * Displays a screen where they can enter a new view.
699
     *
700
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
701
     */
702
    public function doCreate($msg = '')
703
    {
704
        $lang = $this->lang;
705
        $data = $this->misc->getDatabaseAccessor();
706
707
        if (!isset($_REQUEST['formView'])) {
708
            $_REQUEST['formView'] = '';
709
        }
710
711
        if (!isset($_REQUEST['formDefinition'])) {
712
            if (isset($_SESSION['sqlquery'])) {
713
                $_REQUEST['formDefinition'] = $_SESSION['sqlquery'];
714
            } else {
715
                $_REQUEST['formDefinition'] = 'SELECT ';
716
            }
717
        }
718
        if (!isset($_REQUEST['formComment'])) {
719
            $_REQUEST['formComment'] = '';
720
        }
721
722
        $this->printTrail('schema');
723
        $this->printTitle($lang['strcreateview'], 'pg.view.create');
724
        $this->printMsg($msg);
725
726
        echo '<form action="' . \SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
727
        echo "<table style=\"width: 100%\">\n";
728
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
729
        echo "\t<td class=\"data1\"><input name=\"formView\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
730
        htmlspecialchars($_REQUEST['formView']), "\" /></td>\n\t</tr>\n";
731
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strdefinition']}</th>\n";
732
        echo "\t<td class=\"data1\"><textarea style=\"width:100%;\" rows=\"10\" cols=\"50\" name=\"formDefinition\">",
733
        htmlspecialchars($_REQUEST['formDefinition']), "</textarea></td>\n\t</tr>\n";
734
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
735
        echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
736
        htmlspecialchars($_REQUEST['formComment']), "</textarea></td>\n\t</tr>\n";
737
        echo "</table>\n";
738
        echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
739
        echo $this->misc->form;
740
        echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
741
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
742
        echo "</form>\n";
743
    }
744
745
    /**
746
     * Actually creates the new view in the database.
747
     */
748
    public function doSaveCreate()
749
    {
750
        $lang = $this->lang;
751
        $data = $this->misc->getDatabaseAccessor();
752
753
        // Check that they've given a name and a definition
754
        if ('' == $_POST['formView']) {
755
            $this->doCreate($lang['strviewneedsname']);
756
        } elseif ('' == $_POST['formDefinition']) {
757
            $this->doCreate($lang['strviewneedsdef']);
758
        } else {
759
            $status = $data->createView($_POST['formView'], $_POST['formDefinition'], false, $_POST['formComment']);
760
            if (0 == $status) {
761
                $this->misc->setReloadBrowser(true);
762
                $this->doDefault($lang['strviewcreated']);
763
            } else {
764
                $this->doCreate($lang['strviewcreatedbad']);
765
            }
766
        }
767
    }
768
769
    /**
770
     * Actually creates the new wizard view in the database.
771
     */
772
    public function doSaveCreateWiz()
773
    {
774
        $lang = $this->lang;
775
        $data = $this->misc->getDatabaseAccessor();
776
777
        // Check that they've given a name and fields they want to select
778
779
        if (!strlen($_POST['formView'])) {
780
            $this->doSetParamsCreate($lang['strviewneedsname']);
781
        } elseif (!isset($_POST['formFields']) || !count($_POST['formFields'])) {
782
            $this->doSetParamsCreate($lang['strviewneedsfields']);
783
        } else {
784
            $selFields = '';
785
786
            if (!empty($_POST['dblFldMeth'])) {
787
                $tmpHsh = [];
788
            }
789
790
            foreach ($_POST['formFields'] as $curField) {
791
                $arrTmp = unserialize($curField);
792
                $data->fieldArrayClean($arrTmp);
793
                if (!empty($_POST['dblFldMeth'])) {
794
                    // doublon control
795
                    if (empty($tmpHsh[$arrTmp['fieldname']])) {
796
                        // field does not exist
797
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
798
                        $tmpHsh[$arrTmp['fieldname']] = 1;
799
                    } elseif ('rename' == $_POST['dblFldMeth']) {
800
                        // field exist and must be renamed
801
                        ++$tmpHsh[$arrTmp['fieldname']];
802
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" AS \"{$arrTmp['schemaname']}_{$arrTmp['tablename']}_{$arrTmp['fieldname']}{$tmpHsh[$arrTmp['fieldname']]}\", ";
803
                    }
804
                    // field already exist, just ignore this one
805
                } else {
806
                    // no doublon control
807
                    $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
808
                }
809
            }
810
811
            $selFields = substr($selFields, 0, -2);
812
            unset($arrTmp, $tmpHsh);
813
            $linkFields = '';
814
815
            // If we have links, out put the JOIN ... ON statements
816
            if (is_array($_POST['formLink'])) {
817
                // Filter out invalid/blank entries for our links
818
                $arrLinks = [];
819
                foreach ($_POST['formLink'] as $curLink) {
820
                    if (strlen($curLink['leftlink']) && strlen($curLink['rightlink']) && strlen($curLink['operator'])) {
821
                        $arrLinks[] = $curLink;
822
                    }
823
                }
824
                // We must perform some magic to make sure that we have a valid join order
825
                $count       = sizeof($arrLinks);
826
                $arrJoined   = [];
827
                $arrUsedTbls = [];
828
829
                // If we have at least one join condition, output it
830
                if ($count > 0) {
831
                    $j = 0;
832
                    while ($j < $count) {
833
                        foreach ($arrLinks as $curLink) {
834
                            $arrLeftLink  = unserialize($curLink['leftlink']);
835
                            $arrRightLink = unserialize($curLink['rightlink']);
836
                            $data->fieldArrayClean($arrLeftLink);
837
                            $data->fieldArrayClean($arrRightLink);
838
839
                            $tbl1 = "\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\"";
840
                            $tbl2 = "\"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\"";
841
842
                            if ((!in_array($curLink, $arrJoined, true) && in_array($tbl1, $arrUsedTbls, true)) || !count($arrJoined)) {
843
                                // Make sure for multi-column foreign keys that we use a table alias tables joined to more than once
844
                                // This can (and should be) more optimized for multi-column foreign keys
845
                                $adj_tbl2 = in_array($tbl2, $arrUsedTbls, true) ? "${tbl2} AS alias_ppa_" . mktime() : $tbl2;
846
847
                                $linkFields .= strlen($linkFields) ? "{$curLink['operator']} ${adj_tbl2} ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") "
848
                                : "${tbl1} {$curLink['operator']} ${adj_tbl2} ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") ";
849
850
                                $arrJoined[] = $curLink;
851
                                if (!in_array($tbl1, $arrUsedTbls, true)) {
852
                                    $arrUsedTbls[] = $tbl1;
853
                                }
854
855
                                if (!in_array($tbl2, $arrUsedTbls, true)) {
856
                                    $arrUsedTbls[] = $tbl2;
857
                                }
858
                            }
859
                        }
860
                        ++$j;
861
                    }
862
                }
863
            }
864
865
            //if linkfields has no length then either _POST['formLink'] was not set, or there were no join conditions
866
            //just select from all seleted tables - a cartesian join do a
867
            if (!strlen($linkFields)) {
868
                foreach ($_POST['formTables'] as $curTable) {
869
                    $arrTmp = unserialize($curTable);
870
                    $data->fieldArrayClean($arrTmp);
871
                    $linkFields .= strlen($linkFields) ? ", \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"" : "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"";
872
                }
873
            }
874
875
            $addConditions = '';
876
            if (is_array($_POST['formCondition'])) {
877
                foreach ($_POST['formCondition'] as $curCondition) {
878
                    if (strlen($curCondition['field']) && strlen($curCondition['txt'])) {
879
                        $arrTmp = unserialize($curCondition['field']);
880
                        $data->fieldArrayClean($arrTmp);
881
                        $addConditions .= strlen($addConditions) ? " AND \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' "
882
                        : " \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
883
                    }
884
                }
885
            }
886
887
            $viewQuery = "SELECT ${selFields} FROM ${linkFields} ";
888
889
            //add where from additional conditions
890
            if (strlen($addConditions)) {
891
                $viewQuery .= ' WHERE ' . $addConditions;
892
            }
893
894
            $status = $data->createView($_POST['formView'], $viewQuery, false, $_POST['formComment']);
895
            if (0 == $status) {
896
                $this->misc->setReloadBrowser(true);
897
                $this->doDefault($lang['strviewcreated']);
898
            } else {
899
                $this->doSetParamsCreate($lang['strviewcreatedbad']);
900
            }
901
        }
902
    }
903
}
904