Passed
Pull Request — develop (#92)
by Felipe
04:25
created

MaterializedviewsController::render()   D

Complexity

Conditions 17
Paths 17

Size

Total Lines 81
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

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

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