Code Duplication    Length = 884-885 lines in 2 locations

src/controllers/MaterializedviewsController.php 1 location

@@ 10-894 (lines=885) @@
7
/**
8
 * Base controller class
9
 */
10
class MaterializedviewsController extends BaseController
11
{
12
    public $script      = 'materializedviews.php';
13
    public $_name       = 'MaterializedviewsController';
14
    public $table_place = 'matviews-matviews';
15
16
    public function render()
17
    {
18
        $conf   = $this->conf;
19
        $misc   = $this->misc;
20
        $lang   = $this->lang;
21
        $action = $this->action;
22
23
        if ($action == 'tree') {
24
            return $this->doTree();
25
        } elseif ($action == 'subtree') {
26
            return $this->doSubTree();
27
        }
28
29
        $data = $misc->getDatabaseAccessor();
30
31
        $this->printHeader('M ' . $lang['strviews']);
32
        $this->printBody();
33
34
        switch ($action) {
35
            case 'selectrows':
36
                if (!isset($_REQUEST['cancel'])) {
37
                    $this->doSelectRows(false);
38
                } else {
39
                    $this->doDefault();
40
                }
41
42
                break;
43
            case 'confselectrows':
44
                $this->doSelectRows(true);
45
                break;
46
            case 'save_create_wiz':
47
                if (isset($_REQUEST['cancel'])) {
48
                    $this->doDefault();
49
                } else {
50
                    $this->doSaveCreateWiz();
51
                }
52
53
                break;
54
            case 'wiz_create':
55
                $this->doWizardCreate();
56
                break;
57
            case 'set_params_create':
58
                if (isset($_POST['cancel'])) {
59
                    $this->doDefault();
60
                } else {
61
                    $this->doSetParamsCreate();
62
                }
63
64
                break;
65
            case 'save_create':
66
                if (isset($_REQUEST['cancel'])) {
67
                    $this->doDefault();
68
                } else {
69
                    $this->doSaveCreate();
70
                }
71
72
                break;
73
            case 'create':
74
                $this->doCreate();
75
                break;
76
            case 'drop':
77
                if (isset($_POST['drop'])) {
78
                    $this->doDrop(false);
79
                } else {
80
                    $this->doDefault();
81
                }
82
83
                break;
84
            case 'confirm_drop':
85
                $this->doDrop(true);
86
                break;
87
            default:
88
                $this->doDefault();
89
                break;
90
        }
91
92
        $this->printFooter();
93
    }
94
95
    /**
96
     * Show default list of views in the database
97
     */
98
    public function doDefault($msg = '')
99
    {
100
        $conf = $this->conf;
101
        $misc = $this->misc;
102
        $lang = $this->lang;
103
        $data = $misc->getDatabaseAccessor();
104
105
        $this->printTrail('schema');
106
        $this->printTabs('schema', 'matviews');
107
        $this->printMsg($msg);
108
109
        //$matviews = $data->getViews();
110
        $matviews = $data->getMaterializedViews();
111
112
        $columns = [
113
            'matview' => [
114
                'title' => 'M ' . $lang['strview'],
115
                'field' => Decorator::field('relname'),
116
                'url'   => SUBFOLDER . "/redirect/matview?{$misc->href}&",
117
                'vars'  => ['matview' => 'relname'],
118
            ],
119
            'owner'   => [
120
                'title' => $lang['strowner'],
121
                'field' => Decorator::field('relowner'),
122
            ],
123
            'actions' => [
124
                'title' => $lang['stractions'],
125
            ],
126
            'comment' => [
127
                'title' => $lang['strcomment'],
128
                'field' => Decorator::field('relcomment'),
129
            ],
130
        ];
131
132
        $actions = [
133
            'multiactions' => [
134
                'keycols' => ['matview' => 'relname'],
135
                'url'     => 'materializedviews.php',
136
            ],
137
            'browse'       => [
138
                'content' => $lang['strbrowse'],
139
                'attr'    => [
140
                    'href' => [
141
                        'url'     => 'display.php',
142
                        'urlvars' => [
143
                            'action'  => 'confselectrows',
144
                            'subject' => 'matview',
145
                            'return'  => 'schema',
146
                            'matview' => Decorator::field('relname'),
147
                        ],
148
                    ],
149
                ],
150
            ],
151
            'select'       => [
152
                'content' => $lang['strselect'],
153
                'attr'    => [
154
                    'href' => [
155
                        'url'     => 'materializedviews.php',
156
                        'urlvars' => [
157
                            'action'  => 'confselectrows',
158
                            'matview' => Decorator::field('relname'),
159
                        ],
160
                    ],
161
                ],
162
            ],
163
164
            // Insert is possible if the relevant rule for the view has been created.
165
            //            'insert' => array(
166
            //                'title'    => $lang['strinsert'],
167
            //                'url'    => "materializedviews.php?action=confinsertrow&{$misc->href}&",
168
            //                'vars'    => array('view' => 'relname'),
169
            //            ),
170
171
            'alter'        => [
172
                'content' => $lang['stralter'],
173
                'attr'    => [
174
                    'href' => [
175
                        'url'     => 'materializedviewproperties.php',
176
                        'urlvars' => [
177
                            'action'  => 'confirm_alter',
178
                            'matview' => Decorator::field('relname'),
179
                        ],
180
                    ],
181
                ],
182
            ],
183
            'drop'         => [
184
                'multiaction' => 'confirm_drop',
185
                'content'     => $lang['strdrop'],
186
                'attr'        => [
187
                    'href' => [
188
                        'url'     => 'materializedviews.php',
189
                        'urlvars' => [
190
                            'action'  => 'confirm_drop',
191
                            'matview' => Decorator::field('relname'),
192
                        ],
193
                    ],
194
                ],
195
            ],
196
        ];
197
198
        echo $this->printTable($matviews, $columns, $actions, $this->table_place, $lang['strnoviews']);
199
200
        $navlinks = [
201
            'create'    => [
202
                'attr'    => [
203
                    'href' => [
204
                        'url'     => 'materializedviews.php',
205
                        'urlvars' => [
206
                            'action'   => 'create',
207
                            'server'   => $_REQUEST['server'],
208
                            'database' => $_REQUEST['database'],
209
                            'schema'   => $_REQUEST['schema'],
210
                        ],
211
                    ],
212
                ],
213
                'content' => $lang['strcreateview'],
214
            ],
215
            'createwiz' => [
216
                'attr'    => [
217
                    'href' => [
218
                        'url'     => 'materializedviews.php',
219
                        'urlvars' => [
220
                            'action'   => 'wiz_create',
221
                            'server'   => $_REQUEST['server'],
222
                            'database' => $_REQUEST['database'],
223
                            'schema'   => $_REQUEST['schema'],
224
                        ],
225
                    ],
226
                ],
227
                'content' => $lang['strcreateviewwiz'],
228
            ],
229
        ];
230
        $this->printNavLinks($navlinks, $this->table_place, get_defined_vars());
231
    }
232
233
    /**
234
     * Generate XML for the browser tree.
235
     */
236
    public function doTree()
237
    {
238
        $conf = $this->conf;
239
        $misc = $this->misc;
240
        $lang = $this->lang;
241
        $data = $misc->getDatabaseAccessor();
242
243
        $matviews = $data->getMaterializedViews();
244
245
        $reqvars = $misc->getRequestVars('matview');
246
247
        $attrs = [
248
            'text'       => Decorator::field('relname'),
249
            'icon'       => 'MView',
250
            'iconAction' => Decorator::url('display.php', $reqvars, ['matview' => Decorator::field('relname')]),
251
            'toolTip'    => Decorator::field('relcomment'),
252
            'action'     => Decorator::redirecturl('redirect.php', $reqvars, ['matview' => Decorator::field('relname')]),
253
            'branch'     => Decorator::url('materializedviews.php', $reqvars, ['action' => 'subtree', 'matview' => Decorator::field('relname')]),
254
        ];
255
256
        return $this->printTree($matviews, $attrs, 'matviews');
257
    }
258
259
    public function doSubTree()
260
    {
261
        $conf = $this->conf;
262
        $misc = $this->misc;
263
        $lang = $this->lang;
264
        $data = $misc->getDatabaseAccessor();
265
266
        $tabs    = $misc->getNavTabs('matview');
267
        $items   = $this->adjustTabsForTree($tabs);
268
        $reqvars = $misc->getRequestVars('matview');
269
270
        $attrs = [
271
            'text'   => Decorator::field('title'),
272
            'icon'   => Decorator::field('icon'),
273
            'action' => Decorator::actionurl(Decorator::field('url'), $reqvars, Decorator::field('urlvars'), ['matview' => $_REQUEST['matview']]),
274
            'branch' => Decorator::ifempty(
275
                Decorator::field('branch'), '', Decorator::url(Decorator::field('url'), Decorator::field('urlvars'), $reqvars,
276
                    [
277
                        'action'  => 'tree',
278
                        'matview' => $_REQUEST['matview'],
279
                    ]
280
                )
281
            ),
282
        ];
283
284
        return $this->printTree($items, $attrs, 'matviews');
285
    }
286
287
    /**
288
     * Ask for select parameters and perform select
289
     */
290
    public function doSelectRows($confirm, $msg = '')
291
    {
292
        $conf = $this->conf;
293
        $misc = $this->misc;
294
        $lang = $this->lang;
295
        $data = $misc->getDatabaseAccessor();
296
297
        if ($confirm) {
298
            $this->printTrail('view');
299
            $this->printTabs('matview', 'select');
300
            $this->printMsg($msg);
301
302
            $attrs = $data->getTableAttributes($_REQUEST['matview']);
303
304
            echo '<form action="' . SUBFOLDER . '/src/views/' . $this->script . '" method="post" id="selectform">';
305
            echo "\n";
306
307
            if ($attrs->recordCount() > 0) {
308
                // JavaScript for select all feature
309
                echo "<script type=\"text/javascript\">\n";
310
                echo "//<![CDATA[\n";
311
                echo "	function selectAll() {\n";
312
                echo "		for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n";
313
                echo "			var e = document.getElementById('selectform').elements[i];\n";
314
                echo "			if (e.name.indexOf('show') == 0) { \n ";
315
                echo "				e.checked = document.getElementById('selectform').selectall.checked;\n";
316
                echo "			}\n";
317
                echo "		}\n";
318
                echo "	}\n";
319
                echo "//]]>\n";
320
                echo "</script>\n";
321
322
                echo "<table>\n";
323
324
                // Output table header
325
                echo "<tr><th class=\"data\">{$lang['strshow']}</th><th class=\"data\">{$lang['strcolumn']}</th>";
326
                echo "<th class=\"data\">{$lang['strtype']}</th><th class=\"data\">{$lang['stroperator']}</th>";
327
                echo "<th class=\"data\">{$lang['strvalue']}</th></tr>";
328
329
                $i = 0;
330
                while (!$attrs->EOF) {
331
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
332
                    // Set up default value if there isn't one already
333
                    if (!isset($_REQUEST['values'][$attrs->fields['attname']])) {
334
                        $_REQUEST['values'][$attrs->fields['attname']] = null;
335
                    }
336
337
                    if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) {
338
                        $_REQUEST['ops'][$attrs->fields['attname']] = null;
339
                    }
340
341
                    // Continue drawing row
342
                    $id = (($i % 2) == 0 ? '1' : '2');
343
                    echo "<tr class=\"data{$id}\">\n";
344
                    echo '<td style="white-space:nowrap;">';
345
                    echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"',
346
                    isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>';
347
                    echo '<td style="white-space:nowrap;">', $misc->printVal($attrs->fields['attname']), '</td>';
348
                    echo '<td style="white-space:nowrap;">', $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>';
349
                    echo '<td style="white-space:nowrap;">';
350
                    echo "<select name=\"ops[{$attrs->fields['attname']}]\">\n";
351
                    foreach (array_keys($data->selectOps) as $v) {
352
                        echo '<option value="', htmlspecialchars($v), '"', ($v == $_REQUEST['ops'][$attrs->fields['attname']]) ? ' selected="selected"' : '',
353
                        '>', htmlspecialchars($v), "</option>\n";
354
                    }
355
                    echo "</select></td>\n";
356
                    echo '<td style="white-space:nowrap;">', $data->printField("values[{$attrs->fields['attname']}]",
357
                        $_REQUEST['values'][$attrs->fields['attname']], $attrs->fields['type']), '</td>';
358
                    echo "</tr>\n";
359
                    $i++;
360
                    $attrs->moveNext();
361
                }
362
                // Select all checkbox
363
                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>";
364
                echo "</table>\n";
365
            } else {
366
                echo "<p>{$lang['strinvalidparam']}</p>\n";
367
            }
368
369
            echo "<p><input type=\"hidden\" name=\"action\" value=\"selectrows\" />\n";
370
            echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['matview']), "\" />\n";
371
            echo "<input type=\"hidden\" name=\"subject\" value=\"view\" />\n";
372
            echo $misc->form;
373
            echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$lang['strselect']}\" />\n";
374
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
375
            echo "</form>\n";
376
            return;
377
        } else {
378
            if (!isset($_POST['show'])) {
379
                $_POST['show'] = [];
380
            }
381
382
            if (!isset($_POST['values'])) {
383
                $_POST['values'] = [];
384
            }
385
386
            if (!isset($_POST['nulls'])) {
387
                $_POST['nulls'] = [];
388
            }
389
390
            // Verify that they haven't supplied a value for unary operators
391
            foreach ($_POST['ops'] as $k => $v) {
392
                if ($data->selectOps[$v] == 'p' && $_POST['values'][$k] != '') {
393
                    $this->doSelectRows(true, $lang['strselectunary']);
394
                    return;
395
                }
396
            }
397
398
            if (sizeof($_POST['show']) == 0) {
399
                return $this->doSelectRows(true, $lang['strselectneedscol']);
400
            } else {
401
                // Generate query SQL
402
                $query = $data->getSelectSQL($_REQUEST['matview'], array_keys($_POST['show']), $_POST['values'], $_POST['ops']);
403
404
                $_REQUEST['query']  = $query;
405
                $_REQUEST['return'] = 'schema';
406
407
                $this->setNoOutput(true);
408
409
                $display_controller = new DisplayController($this->getContainer());
410
411
                return $display_controller->render();
412
            }
413
        }
414
    }
415
416
    /**
417
     * Show confirmation of drop and perform actual drop
418
     */
419
    public function doDrop($confirm)
420
    {
421
        $conf = $this->conf;
422
        $misc = $this->misc;
423
        $lang = $this->lang;
424
        $data = $misc->getDatabaseAccessor();
425
426
        if (empty($_REQUEST['matview']) && empty($_REQUEST['ma'])) {
427
            $this->doDefault($lang['strspecifyviewtodrop']);
428
            exit();
429
        }
430
431
        if ($confirm) {
432
            $this->printTrail('getTrail');
433
            $this->printTitle($lang['strdrop'], 'pg.matview.drop');
434
435
            echo '<form action="' . SUBFOLDER . "/src/views/materializedviews.php\" method=\"post\">\n";
436
437
            //If multi drop
438
            if (isset($_REQUEST['ma'])) {
439
                foreach ($_REQUEST['ma'] as $v) {
440
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
441
                    echo '<p>', sprintf($lang['strconfdropview'], $misc->printVal($a['view'])), "</p>\n";
442
                    echo '<input type="hidden" name="view[]" value="', htmlspecialchars($a['view']), "\" />\n";
443
                }
444
            } else {
445
                echo '<p>', sprintf($lang['strconfdropview'], $misc->printVal($_REQUEST['matview'])), "</p>\n";
446
                echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['matview']), "\" />\n";
447
            }
448
449
            echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
450
451
            echo $misc->form;
452
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
453
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
454
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
455
            echo "</form>\n";
456
        } else {
457
            if (is_array($_POST['view'])) {
458
                $msg    = '';
459
                $status = $data->beginTransaction();
460
                if ($status == 0) {
461
                    foreach ($_POST['view'] as $s) {
462
                        $status = $data->dropView($s, isset($_POST['cascade']));
463
                        if ($status == 0) {
464
                            $msg .= sprintf('%s: %s<br />', htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdropped']);
465
                        } else {
466
                            $data->endTransaction();
467
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdroppedbad']));
468
                            return;
469
                        }
470
                    }
471
                }
472
                if ($data->endTransaction() == 0) {
473
                    // Everything went fine, back to the Default page....
474
                    $this->misc->setReloadBrowser(true);
475
                    $this->doDefault($msg);
476
                } else {
477
                    $this->doDefault($lang['strviewdroppedbad']);
478
                }
479
            } else {
480
                $status = $data->dropView($_POST['view'], isset($_POST['cascade']));
481
                if ($status == 0) {
482
                    $this->misc->setReloadBrowser(true);
483
                    $this->doDefault($lang['strviewdropped']);
484
                } else {
485
                    $this->doDefault($lang['strviewdroppedbad']);
486
                }
487
            }
488
        }
489
    }
490
491
    /**
492
     * Sets up choices for table linkage, and which fields to select for the view we're creating
493
     */
494
    public function doSetParamsCreate($msg = '')
495
    {
496
        $conf = $this->conf;
497
        $misc = $this->misc;
498
        $lang = $this->lang;
499
        $data = $misc->getDatabaseAccessor();
500
501
        // Check that they've chosen tables for the view definition
502
        if (!isset($_POST['formTables'])) {
503
            $this->doWizardCreate($lang['strviewneedsdef']);
504
        } else {
505
            // Initialise variables
506
            if (!isset($_REQUEST['formView'])) {
507
                $_REQUEST['formView'] = '';
508
            }
509
510
            if (!isset($_REQUEST['formComment'])) {
511
                $_REQUEST['formComment'] = '';
512
            }
513
514
            $this->printTrail('schema');
515
            $this->printTitle($lang['strcreateviewwiz'], 'pg.matview.create');
516
            $this->printMsg($msg);
517
518
            $tblCount = sizeof($_POST['formTables']);
519
            //unserialize our schema/table information and store in arrSelTables
520
            for ($i = 0; $i < $tblCount; $i++) {
521
                $arrSelTables[] = unserialize($_POST['formTables'][$i]);
522
            }
523
524
            $linkCount = $tblCount;
525
526
            //get linking keys
527
            $rsLinkKeys = $data->getLinkingKeys($arrSelTables);
528
            $linkCount  = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
529
530
            $arrFields = []; //array that will hold all our table/field names
531
532
            //if we have schemas we need to specify the correct schema for each table we're retrieiving
533
            //with getTableAttributes
534
            $curSchema = $data->_schema;
535
            for ($i = 0; $i < $tblCount; $i++) {
536
                if ($data->_schema != $arrSelTables[$i]['schemaname']) {
537
                    $data->setSchema($arrSelTables[$i]['schemaname']);
538
                }
539
540
                $attrs = $data->getTableAttributes($arrSelTables[$i]['tablename']);
541
                while (!$attrs->EOF) {
542
                    $arrFields["{$arrSelTables[$i]['schemaname']}.{$arrSelTables[$i]['tablename']}.{$attrs->fields['attname']}"] = serialize([
543
                        'schemaname' => $arrSelTables[$i]['schemaname'],
544
                        'tablename'  => $arrSelTables[$i]['tablename'],
545
                        'fieldname'  => $attrs->fields['attname']]
546
                    );
547
                    $attrs->moveNext();
548
                }
549
550
                $data->setSchema($curSchema);
551
            }
552
            asort($arrFields);
553
554
            echo '<form action="' . SUBFOLDER . "/src/views/materializedviews.php\" method=\"post\">\n";
555
            echo "<table>\n";
556
            echo "<tr><th class=\"data\">{$lang['strviewname']}</th></tr>";
557
            echo "<tr>\n<td class=\"data1\">\n";
558
            // View name
559
            echo '<input name="formView" value="', htmlspecialchars($_REQUEST['formView']), "\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />\n";
560
            echo "</td>\n</tr>\n";
561
            echo "<tr><th class=\"data\">{$lang['strcomment']}</th></tr>";
562
            echo "<tr>\n<td class=\"data1\">\n";
563
            // View comments
564
            echo '<textarea name="formComment" rows="3" cols="32">',
565
            htmlspecialchars($_REQUEST['formComment']), "</textarea>\n";
566
            echo "</td>\n</tr>\n";
567
            echo "</table>\n";
568
569
            // Output selector for fields to be retrieved from view
570
            echo "<table>\n";
571
            echo "<tr><th class=\"data\">{$lang['strcolumns']}</th></tr>";
572
            echo "<tr>\n<td class=\"data1\">\n";
573
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, 'formFields[]', false, '', true);
574
            echo "</td>\n</tr>";
575
            echo "<tr><td><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth1\" value=\"rename\" /><label for=\"dblFldMeth1\">{$lang['strrenamedupfields']}</label>";
576
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth2\" value=\"drop\" /><label for=\"dblFldMeth2\">{$lang['strdropdupfields']}</label>";
577
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth3\" value=\"\" checked=\"checked\" /><label for=\"dblFldMeth3\">{$lang['strerrordupfields']}</label></td></tr></table><br />";
578
579
            // Output the Linking keys combo boxes
580
            echo "<table>\n";
581
            echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";
582
            $rowClass = 'data1';
583
            for ($i = 0; $i < $linkCount; $i++) {
584
                // Initialise variables
585
                if (!isset($formLink[$i]['operator'])) {
586
                    $formLink[$i]['operator'] = 'INNER JOIN';
587
                }
588
589
                echo "<tr>\n<td class=\"$rowClass\">\n";
590
591
                if (!$rsLinkKeys->EOF) {
592
                    $curLeftLink  = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['p_schema'], 'tablename' => $rsLinkKeys->fields['p_table'], 'fieldname' => $rsLinkKeys->fields['p_field']]));
593
                    $curRightLink = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['f_schema'], 'tablename' => $rsLinkKeys->fields['f_table'], 'fieldname' => $rsLinkKeys->fields['f_field']]));
594
                    $rsLinkKeys->moveNext();
595
                } else {
596
                    $curLeftLink  = '';
597
                    $curRightLink = '';
598
                }
599
600
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[$i][leftlink]", true, $curLeftLink, false);
601
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($data->joinOps, "formLink[$i][operator]", true, $formLink[$i]['operator']);
602
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[$i][rightlink]", true, $curRightLink, false);
603
                echo "</td>\n</tr>\n";
604
                $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';
605
            }
606
            echo "</table>\n<br />\n";
607
608
            // Build list of available operators (infix only)
609
            $arrOperators = [];
610
            foreach ($data->selectOps as $k => $v) {
611
                if ($v == 'i') {
612
                    $arrOperators[$k] = $k;
613
                }
614
            }
615
616
            // Output additional conditions, note that this portion of the wizard treats the right hand side as literal values
617
            //(not as database objects) so field names will be treated as strings, use the above linking keys section to perform joins
618
            echo "<table>\n";
619
            echo "<tr><th class=\"data\">{$lang['strviewconditions']}</th></tr>";
620
            $rowClass = 'data1';
621
            for ($i = 0; $i < $linkCount; $i++) {
622
                echo "<tr>\n<td class=\"$rowClass\">\n";
623
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formCondition[$i][field]");
624
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrOperators, "formCondition[$i][operator]", false, false);
625
                echo "<input type=\"text\" name=\"formCondition[$i][txt]\" />\n";
626
                echo "</td>\n</tr>\n";
627
                $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';
628
            }
629
            echo "</table>\n";
630
            echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create_wiz\" />\n";
631
632
            foreach ($arrSelTables as $curTable) {
633
                echo '<input type="hidden" name="formTables[]" value="' . htmlspecialchars(serialize($curTable)) . "\" />\n";
634
            }
635
636
            echo $misc->form;
637
            echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
638
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
639
            echo "</form>\n";
640
        }
641
    }
642
643
    /**
644
     * Display a wizard where they can enter a new view
645
     */
646
    public function doWizardCreate($msg = '')
647
    {
648
        $conf = $this->conf;
649
        $misc = $this->misc;
650
        $lang = $this->lang;
651
        $data = $misc->getDatabaseAccessor();
652
653
        $tables = $data->getTables(true);
654
655
        $this->printTrail('schema');
656
        $this->printTitle($lang['strcreateviewwiz'], 'pg.matview.create');
657
        $this->printMsg($msg);
658
659
        echo '<form action="' . SUBFOLDER . "/src/views/materializedviews.php\" method=\"post\">\n";
660
        echo "<table>\n";
661
        echo "<tr><th class=\"data\">{$lang['strtables']}</th></tr>";
662
        echo "<tr>\n<td class=\"data1\">\n";
663
664
        $arrTables = [];
665
        while (!$tables->EOF) {
666
            $arrTmp                                                                   = [];
667
            $arrTmp['schemaname']                                                     = $tables->fields['nspname'];
668
            $arrTmp['tablename']                                                      = $tables->fields['relname'];
669
            $arrTables[$tables->fields['nspname'] . '.' . $tables->fields['relname']] = serialize($arrTmp);
670
            $tables->moveNext();
671
        }
672
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrTables, 'formTables[]', false, '', true);
673
674
        echo "</td>\n</tr>\n";
675
        echo "</table>\n";
676
        echo "<p><input type=\"hidden\" name=\"action\" value=\"set_params_create\" />\n";
677
        echo $misc->form;
678
        echo "<input type=\"submit\" value=\"{$lang['strnext']}\" />\n";
679
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
680
        echo "</form>\n";
681
    }
682
683
    /**
684
     * Displays a screen where they can enter a new view
685
     */
686
    public function doCreate($msg = '')
687
    {
688
        $conf = $this->conf;
689
        $misc = $this->misc;
690
        $lang = $this->lang;
691
        $data = $misc->getDatabaseAccessor();
692
693
        if (!isset($_REQUEST['formView'])) {
694
            $_REQUEST['formView'] = '';
695
        }
696
697
        if (!isset($_REQUEST['formDefinition'])) {
698
            if (isset($_SESSION['sqlquery'])) {
699
                $_REQUEST['formDefinition'] = $_SESSION['sqlquery'];
700
            } else {
701
                $_REQUEST['formDefinition'] = 'SELECT ';
702
            }
703
        }
704
        if (!isset($_REQUEST['formComment'])) {
705
            $_REQUEST['formComment'] = '';
706
        }
707
708
        $this->printTrail('schema');
709
        $this->printTitle($lang['strcreateview'], 'pg.matview.create');
710
        $this->printMsg($msg);
711
712
        echo '<form action="' . SUBFOLDER . "/src/views/materializedviews.php\" method=\"post\">\n";
713
        echo "<table style=\"width: 100%\">\n";
714
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
715
        echo "\t<td class=\"data1\"><input name=\"formView\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
716
        htmlspecialchars($_REQUEST['formView']), "\" /></td>\n\t</tr>\n";
717
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strdefinition']}</th>\n";
718
        echo "\t<td class=\"data1\"><textarea style=\"width:100%;\" rows=\"10\" cols=\"50\" name=\"formDefinition\">",
719
        htmlspecialchars($_REQUEST['formDefinition']), "</textarea></td>\n\t</tr>\n";
720
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
721
        echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
722
        htmlspecialchars($_REQUEST['formComment']), "</textarea></td>\n\t</tr>\n";
723
        echo "</table>\n";
724
        echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
725
        echo $misc->form;
726
        echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
727
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
728
        echo "</form>\n";
729
    }
730
731
    /**
732
     * Actually creates the new view in the database
733
     */
734
    public function doSaveCreate()
735
    {
736
        $conf = $this->conf;
737
        $misc = $this->misc;
738
        $lang = $this->lang;
739
        $data = $misc->getDatabaseAccessor();
740
741
        // Check that they've given a name and a definition
742
        if ($_POST['formView'] == '') {
743
            $this->doCreate($lang['strviewneedsname']);
744
        } elseif ($_POST['formDefinition'] == '') {
745
            $this->doCreate($lang['strviewneedsdef']);
746
        } else {
747
            $status = $data->createView($_POST['formView'], $_POST['formDefinition'], false, $_POST['formComment']);
748
            if ($status == 0) {
749
                $this->misc->setReloadBrowser(true);
750
                $this->doDefault($lang['strviewcreated']);
751
            } else {
752
                $this->doCreate($lang['strviewcreatedbad']);
753
            }
754
        }
755
    }
756
757
    /**
758
     * Actually creates the new wizard view in the database
759
     */
760
    public function doSaveCreateWiz()
761
    {
762
        $conf = $this->conf;
763
        $misc = $this->misc;
764
        $lang = $this->lang;
765
        $data = $misc->getDatabaseAccessor();
766
767
        // Check that they've given a name and fields they want to select
768
769
        if (!strlen($_POST['formView'])) {
770
            $this->doSetParamsCreate($lang['strviewneedsname']);
771
        } elseif (!isset($_POST['formFields']) || !count($_POST['formFields'])) {
772
            $this->doSetParamsCreate($lang['strviewneedsfields']);
773
        } else {
774
            $selFields = '';
775
776
            if (!empty($_POST['dblFldMeth'])) {
777
                $tmpHsh = [];
778
            }
779
780
            foreach ($_POST['formFields'] as $curField) {
781
                $arrTmp = unserialize($curField);
782
                $data->fieldArrayClean($arrTmp);
783
                if (!empty($_POST['dblFldMeth'])) {
784
                    // doublon control
785
                    if (empty($tmpHsh[$arrTmp['fieldname']])) {
786
                        // field does not exist
787
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
788
                        $tmpHsh[$arrTmp['fieldname']] = 1;
789
                    } elseif ($_POST['dblFldMeth'] == 'rename') {
790
                        // field exist and must be renamed
791
                        $tmpHsh[$arrTmp['fieldname']]++;
792
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" AS \"{$arrTmp['schemaname']}_{$arrTmp['tablename']}_{$arrTmp['fieldname']}{$tmpHsh[$arrTmp['fieldname']]}\", ";
793
                    }
794
                    /* field already exist, just ignore this one */
795
                } else {
796
                    // no doublon control
797
                    $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
798
                }
799
            }
800
801
            $selFields = substr($selFields, 0, -2);
802
            unset($arrTmp, $tmpHsh);
803
            $linkFields = '';
804
805
            // If we have links, out put the JOIN ... ON statements
806
            if (is_array($_POST['formLink'])) {
807
                // Filter out invalid/blank entries for our links
808
                $arrLinks = [];
809
                foreach ($_POST['formLink'] as $curLink) {
810
                    if (strlen($curLink['leftlink']) && strlen($curLink['rightlink']) && strlen($curLink['operator'])) {
811
                        $arrLinks[] = $curLink;
812
                    }
813
                }
814
                // We must perform some magic to make sure that we have a valid join order
815
                $count       = sizeof($arrLinks);
816
                $arrJoined   = [];
817
                $arrUsedTbls = [];
818
819
                // If we have at least one join condition, output it
820
                if ($count > 0) {
821
                    $j = 0;
822
                    while ($j < $count) {
823
                        foreach ($arrLinks as $curLink) {
824
                            $arrLeftLink  = unserialize($curLink['leftlink']);
825
                            $arrRightLink = unserialize($curLink['rightlink']);
826
                            $data->fieldArrayClean($arrLeftLink);
827
                            $data->fieldArrayClean($arrRightLink);
828
829
                            $tbl1 = "\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\"";
830
                            $tbl2 = "\"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\"";
831
832
                            if ((!in_array($curLink, $arrJoined) && in_array($tbl1, $arrUsedTbls)) || !count($arrJoined)) {
833
834
                                // Make sure for multi-column foreign keys that we use a table alias tables joined to more than once
835
                                // This can (and should be) more optimized for multi-column foreign keys
836
                                $adj_tbl2 = in_array($tbl2, $arrUsedTbls) ? "$tbl2 AS alias_ppa_" . mktime() : $tbl2;
837
838
                                $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") "
839
                                : "$tbl1 {$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") ";
840
841
                                $arrJoined[] = $curLink;
842
                                if (!in_array($tbl1, $arrUsedTbls)) {
843
                                    $arrUsedTbls[] = $tbl1;
844
                                }
845
846
                                if (!in_array($tbl2, $arrUsedTbls)) {
847
                                    $arrUsedTbls[] = $tbl2;
848
                                }
849
                            }
850
                        }
851
                        $j++;
852
                    }
853
                }
854
            }
855
856
            //if linkfields has no length then either _POST['formLink'] was not set, or there were no join conditions
857
            //just select from all seleted tables - a cartesian join do a
858
            if (!strlen($linkFields)) {
859
                foreach ($_POST['formTables'] as $curTable) {
860
                    $arrTmp = unserialize($curTable);
861
                    $data->fieldArrayClean($arrTmp);
862
                    $linkFields .= strlen($linkFields) ? ", \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"" : "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"";
863
                }
864
            }
865
866
            $addConditions = '';
867
            if (is_array($_POST['formCondition'])) {
868
                foreach ($_POST['formCondition'] as $curCondition) {
869
                    if (strlen($curCondition['field']) && strlen($curCondition['txt'])) {
870
                        $arrTmp = unserialize($curCondition['field']);
871
                        $data->fieldArrayClean($arrTmp);
872
                        $addConditions .= strlen($addConditions) ? " AND \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' "
873
                        : " \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
874
                    }
875
                }
876
            }
877
878
            $viewQuery = "SELECT $selFields FROM $linkFields ";
879
880
            //add where from additional conditions
881
            if (strlen($addConditions)) {
882
                $viewQuery .= ' WHERE ' . $addConditions;
883
            }
884
885
            $status = $data->createView($_POST['formView'], $viewQuery, false, $_POST['formComment']);
886
            if ($status == 0) {
887
                $this->misc->setReloadBrowser(true);
888
                $this->doDefault($lang['strviewcreated']);
889
            } else {
890
                $this->doSetParamsCreate($lang['strviewcreatedbad']);
891
            }
892
        }
893
    }
894
}
895

src/controllers/ViewsController.php 1 location

@@ 10-893 (lines=884) @@
7
/**
8
 * Base controller class
9
 */
10
class ViewsController extends BaseController
11
{
12
    public $script      = 'views.php';
13
    public $_name       = 'ViewsController';
14
    public $table_place = 'views-views';
15
16
    public function render()
17
    {
18
        $conf   = $this->conf;
19
        $misc   = $this->misc;
20
        $lang   = $this->lang;
21
        $action = $this->action;
22
23
        if ($action == 'tree') {
24
            return $this->doTree();
25
        } elseif ($action == 'subtree') {
26
            return $this->doSubTree();
27
        }
28
29
        $data = $misc->getDatabaseAccessor();
30
31
        $this->printHeader($lang['strviews']);
32
        $this->printBody();
33
34
        switch ($action) {
35
            case 'selectrows':
36
                if (!isset($_REQUEST['cancel'])) {
37
                    $this->doSelectRows(false);
38
                } else {
39
                    $this->doDefault();
40
                }
41
42
                break;
43
            case 'confselectrows':
44
                $this->doSelectRows(true);
45
                break;
46
            case 'save_create_wiz':
47
                if (isset($_REQUEST['cancel'])) {
48
                    $this->doDefault();
49
                } else {
50
                    $this->doSaveCreateWiz();
51
                }
52
53
                break;
54
            case 'wiz_create':
55
                $this->doWizardCreate();
56
                break;
57
            case 'set_params_create':
58
                if (isset($_POST['cancel'])) {
59
                    $this->doDefault();
60
                } else {
61
                    $this->doSetParamsCreate();
62
                }
63
64
                break;
65
            case 'save_create':
66
                if (isset($_REQUEST['cancel'])) {
67
                    $this->doDefault();
68
                } else {
69
                    $this->doSaveCreate();
70
                }
71
72
                break;
73
            case 'create':
74
                $this->doCreate();
75
                break;
76
            case 'drop':
77
                if (isset($_POST['drop'])) {
78
                    $this->doDrop(false);
79
                } else {
80
                    $this->doDefault();
81
                }
82
83
                break;
84
            case 'confirm_drop':
85
                $this->doDrop(true);
86
                break;
87
            default:
88
                $this->doDefault();
89
                break;
90
        }
91
92
        return $this->printFooter();
93
    }
94
95
    /**
96
     * Show default list of views in the database
97
     */
98
    public function doDefault($msg = '')
99
    {
100
        $conf = $this->conf;
101
        $misc = $this->misc;
102
        $lang = $this->lang;
103
        $data = $misc->getDatabaseAccessor();
104
105
        $this->printTrail('schema');
106
        $this->printTabs('schema', 'views');
107
        $this->printMsg($msg);
108
109
        $views = $data->getViews();
110
111
        $columns = [
112
            'view'    => [
113
                'title' => $lang['strview'],
114
                'field' => Decorator::field('relname'),
115
                'url'   => SUBFOLDER . "/redirect/view?{$misc->href}&amp;",
116
                'vars'  => ['view' => 'relname'],
117
            ],
118
            'owner'   => [
119
                'title' => $lang['strowner'],
120
                'field' => Decorator::field('relowner'),
121
            ],
122
            'actions' => [
123
                'title' => $lang['stractions'],
124
            ],
125
            'comment' => [
126
                'title' => $lang['strcomment'],
127
                'field' => Decorator::field('relcomment'),
128
            ],
129
        ];
130
131
        $actions = [
132
            'multiactions' => [
133
                'keycols' => ['view' => 'relname'],
134
                'url'     => 'views.php',
135
            ],
136
            'browse'       => [
137
                'content' => $lang['strbrowse'],
138
                'attr'    => [
139
                    'href' => [
140
                        'url'     => 'display.php',
141
                        'urlvars' => [
142
                            'action'  => 'confselectrows',
143
                            'subject' => 'view',
144
                            'return'  => 'schema',
145
                            'view'    => Decorator::field('relname'),
146
                        ],
147
                    ],
148
                ],
149
            ],
150
            'select'       => [
151
                'content' => $lang['strselect'],
152
                'attr'    => [
153
                    'href' => [
154
                        'url'     => 'views.php',
155
                        'urlvars' => [
156
                            'action' => 'confselectrows',
157
                            'view'   => Decorator::field('relname'),
158
                        ],
159
                    ],
160
                ],
161
            ],
162
163
            // Insert is possible if the relevant rule for the view has been created.
164
            //            'insert' => array(
165
            //                'title'    => $lang['strinsert'],
166
            //                'url'    => "views.php?action=confinsertrow&amp;{$misc->href}&amp;",
167
            //                'vars'    => array('view' => 'relname'),
168
            //            ),
169
170
            'alter'        => [
171
                'content' => $lang['stralter'],
172
                'attr'    => [
173
                    'href' => [
174
                        'url'     => 'viewproperties.php',
175
                        'urlvars' => [
176
                            'action' => 'confirm_alter',
177
                            'view'   => Decorator::field('relname'),
178
                        ],
179
                    ],
180
                ],
181
            ],
182
            'drop'         => [
183
                'multiaction' => 'confirm_drop',
184
                'content'     => $lang['strdrop'],
185
                'attr'        => [
186
                    'href' => [
187
                        'url'     => 'views.php',
188
                        'urlvars' => [
189
                            'action' => 'confirm_drop',
190
                            'view'   => Decorator::field('relname'),
191
                        ],
192
                    ],
193
                ],
194
            ],
195
        ];
196
197
        echo $this->printTable($views, $columns, $actions, $this->table_place, $lang['strnoviews']);
198
199
        $navlinks = [
200
            'create'    => [
201
                'attr'    => [
202
                    'href' => [
203
                        'url'     => 'views.php',
204
                        'urlvars' => [
205
                            'action'   => 'create',
206
                            'server'   => $_REQUEST['server'],
207
                            'database' => $_REQUEST['database'],
208
                            'schema'   => $_REQUEST['schema'],
209
                        ],
210
                    ],
211
                ],
212
                'content' => $lang['strcreateview'],
213
            ],
214
            'createwiz' => [
215
                'attr'    => [
216
                    'href' => [
217
                        'url'     => 'views.php',
218
                        'urlvars' => [
219
                            'action'   => 'wiz_create',
220
                            'server'   => $_REQUEST['server'],
221
                            'database' => $_REQUEST['database'],
222
                            'schema'   => $_REQUEST['schema'],
223
                        ],
224
                    ],
225
                ],
226
                'content' => $lang['strcreateviewwiz'],
227
            ],
228
        ];
229
        $this->printNavLinks($navlinks, $this->table_place, get_defined_vars());
230
    }
231
232
    /**
233
     * Generate XML for the browser tree.
234
     */
235
    public function doTree()
236
    {
237
        $conf = $this->conf;
238
        $misc = $this->misc;
239
        $lang = $this->lang;
240
        $data = $misc->getDatabaseAccessor();
241
242
        $views = $data->getViews();
243
244
        $reqvars = $misc->getRequestVars('view');
245
246
        $attrs = [
247
            'text'       => Decorator::field('relname'),
248
            'icon'       => 'View',
249
            'iconAction' => Decorator::url('display.php', $reqvars, ['view' => Decorator::field('relname')]),
250
            'toolTip'    => Decorator::field('relcomment'),
251
            'action'     => Decorator::redirecturl('redirect.php', $reqvars, ['view' => Decorator::field('relname')]),
252
            'branch'     => Decorator::url('views.php', $reqvars, ['action' => 'subtree', 'view' => Decorator::field('relname')]),
253
        ];
254
255
        return $this->printTree($views, $attrs, 'views');
256
    }
257
258
    public function doSubTree()
259
    {
260
        $conf = $this->conf;
261
        $misc = $this->misc;
262
        $lang = $this->lang;
263
        $data = $misc->getDatabaseAccessor();
264
265
        $tabs    = $misc->getNavTabs('view');
266
        $items   = $this->adjustTabsForTree($tabs);
267
        $reqvars = $misc->getRequestVars('view');
268
269
        $attrs = [
270
            'text'   => Decorator::field('title'),
271
            'icon'   => Decorator::field('icon'),
272
            'action' => Decorator::actionurl(Decorator::field('url'), $reqvars, Decorator::field('urlvars'), ['view' => $_REQUEST['view']]),
273
            'branch' => Decorator::ifempty(
274
                Decorator::field('branch'), '', Decorator::url(Decorator::field('url'), Decorator::field('urlvars'), $reqvars,
275
                    [
276
                        'action' => 'tree',
277
                        'view'   => $_REQUEST['view'],
278
                    ]
279
                )
280
            ),
281
        ];
282
283
        return $this->printTree($items, $attrs, 'view');
284
    }
285
286
    /**
287
     * Ask for select parameters and perform select
288
     */
289
    public function doSelectRows($confirm, $msg = '')
290
    {
291
        $conf = $this->conf;
292
        $misc = $this->misc;
293
        $lang = $this->lang;
294
        $data = $misc->getDatabaseAccessor();
295
296
        if ($confirm) {
297
            $this->printTrail('view');
298
            $this->printTabs('view', 'select');
299
            $this->printMsg($msg);
300
301
            $attrs = $data->getTableAttributes($_REQUEST['view']);
302
303
            echo '<form action="' . SUBFOLDER . '/src/views/' . $this->script . '" method="post" id="selectform">';
304
            echo "\n";
305
306
            if ($attrs->recordCount() > 0) {
307
                // JavaScript for select all feature
308
                echo "<script type=\"text/javascript\">\n";
309
                echo "//<![CDATA[\n";
310
                echo "	function selectAll() {\n";
311
                echo "		for (var i=0; i<document.getElementById('selectform').elements.length; i++) {\n";
312
                echo "			var e = document.getElementById('selectform').elements[i];\n";
313
                echo "			if (e.name.indexOf('show') == 0) { \n ";
314
                echo "				e.checked = document.getElementById('selectform').selectall.checked;\n";
315
                echo "			}\n";
316
                echo "		}\n";
317
                echo "	}\n";
318
                echo "//]]>\n";
319
                echo "</script>\n";
320
321
                echo "<table>\n";
322
323
                // Output table header
324
                echo "<tr><th class=\"data\">{$lang['strshow']}</th><th class=\"data\">{$lang['strcolumn']}</th>";
325
                echo "<th class=\"data\">{$lang['strtype']}</th><th class=\"data\">{$lang['stroperator']}</th>";
326
                echo "<th class=\"data\">{$lang['strvalue']}</th></tr>";
327
328
                $i = 0;
329
                while (!$attrs->EOF) {
330
                    $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
331
                    // Set up default value if there isn't one already
332
                    if (!isset($_REQUEST['values'][$attrs->fields['attname']])) {
333
                        $_REQUEST['values'][$attrs->fields['attname']] = null;
334
                    }
335
336
                    if (!isset($_REQUEST['ops'][$attrs->fields['attname']])) {
337
                        $_REQUEST['ops'][$attrs->fields['attname']] = null;
338
                    }
339
340
                    // Continue drawing row
341
                    $id = (($i % 2) == 0 ? '1' : '2');
342
                    echo "<tr class=\"data{$id}\">\n";
343
                    echo '<td style="white-space:nowrap;">';
344
                    echo '<input type="checkbox" name="show[', htmlspecialchars($attrs->fields['attname']), ']"',
345
                    isset($_REQUEST['show'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /></td>';
346
                    echo '<td style="white-space:nowrap;">', $misc->printVal($attrs->fields['attname']), '</td>';
347
                    echo '<td style="white-space:nowrap;">', $misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod'])), '</td>';
348
                    echo '<td style="white-space:nowrap;">';
349
                    echo "<select name=\"ops[{$attrs->fields['attname']}]\">\n";
350
                    foreach (array_keys($data->selectOps) as $v) {
351
                        echo '<option value="', htmlspecialchars($v), '"', ($v == $_REQUEST['ops'][$attrs->fields['attname']]) ? ' selected="selected"' : '',
352
                        '>', htmlspecialchars($v), "</option>\n";
353
                    }
354
                    echo "</select></td>\n";
355
                    echo '<td style="white-space:nowrap;">', $data->printField("values[{$attrs->fields['attname']}]",
356
                        $_REQUEST['values'][$attrs->fields['attname']], $attrs->fields['type']), '</td>';
357
                    echo "</tr>\n";
358
                    $i++;
359
                    $attrs->moveNext();
360
                }
361
                // Select all checkbox
362
                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>";
363
                echo "</table>\n";
364
            } else {
365
                echo "<p>{$lang['strinvalidparam']}</p>\n";
366
            }
367
368
            echo "<p><input type=\"hidden\" name=\"action\" value=\"selectrows\" />\n";
369
            echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['view']), "\" />\n";
370
            echo "<input type=\"hidden\" name=\"subject\" value=\"view\" />\n";
371
            echo $misc->form;
372
            echo "<input type=\"submit\" name=\"select\" accesskey=\"r\" value=\"{$lang['strselect']}\" />\n";
373
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
374
            echo "</form>\n";
375
            return;
376
        } else {
377
            if (!isset($_POST['show'])) {
378
                $_POST['show'] = [];
379
            }
380
381
            if (!isset($_POST['values'])) {
382
                $_POST['values'] = [];
383
            }
384
385
            if (!isset($_POST['nulls'])) {
386
                $_POST['nulls'] = [];
387
            }
388
389
            // Verify that they haven't supplied a value for unary operators
390
            foreach ($_POST['ops'] as $k => $v) {
391
                if ($data->selectOps[$v] == 'p' && $_POST['values'][$k] != '') {
392
                    $this->doSelectRows(true, $lang['strselectunary']);
393
                    return;
394
                }
395
            }
396
397
            if (sizeof($_POST['show']) == 0) {
398
                return $this->doSelectRows(true, $lang['strselectneedscol']);
399
            } else {
400
                // Generate query SQL
401
                $query = $data->getSelectSQL($_REQUEST['view'], array_keys($_POST['show']), $_POST['values'], $_POST['ops']);
402
403
                $_REQUEST['query']  = $query;
404
                $_REQUEST['return'] = 'schema';
405
406
                $this->setNoOutput(true);
407
408
                $display_controller = new DisplayController($this->getContainer());
409
410
                return $display_controller->render();
411
            }
412
        }
413
    }
414
415
    /**
416
     * Show confirmation of drop and perform actual drop
417
     */
418
    public function doDrop($confirm)
419
    {
420
        $conf = $this->conf;
421
        $misc = $this->misc;
422
        $lang = $this->lang;
423
        $data = $misc->getDatabaseAccessor();
424
425
        if (empty($_REQUEST['view']) && empty($_REQUEST['ma'])) {
426
            $this->doDefault($lang['strspecifyviewtodrop']);
427
            exit();
428
        }
429
430
        if ($confirm) {
431
            $this->printTrail('view');
432
            $this->printTitle($lang['strdrop'], 'pg.view.drop');
433
434
            echo '<form action="' . SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
435
436
            //If multi drop
437
            if (isset($_REQUEST['ma'])) {
438
                foreach ($_REQUEST['ma'] as $v) {
439
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
440
                    echo '<p>', sprintf($lang['strconfdropview'], $misc->printVal($a['view'])), "</p>\n";
441
                    echo '<input type="hidden" name="view[]" value="', htmlspecialchars($a['view']), "\" />\n";
442
                }
443
            } else {
444
                echo '<p>', sprintf($lang['strconfdropview'], $misc->printVal($_REQUEST['view'])), "</p>\n";
445
                echo '<input type="hidden" name="view" value="', htmlspecialchars($_REQUEST['view']), "\" />\n";
446
            }
447
448
            echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
449
450
            echo $misc->form;
451
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
452
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
453
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
454
            echo "</form>\n";
455
        } else {
456
            if (is_array($_POST['view'])) {
457
                $msg    = '';
458
                $status = $data->beginTransaction();
459
                if ($status == 0) {
460
                    foreach ($_POST['view'] as $s) {
461
                        $status = $data->dropView($s, isset($_POST['cascade']));
462
                        if ($status == 0) {
463
                            $msg .= sprintf('%s: %s<br />', htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdropped']);
464
                        } else {
465
                            $data->endTransaction();
466
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($s, ENT_QUOTES, 'UTF-8'), $lang['strviewdroppedbad']));
467
                            return;
468
                        }
469
                    }
470
                }
471
                if ($data->endTransaction() == 0) {
472
                    // Everything went fine, back to the Default page....
473
                    $this->misc->setReloadBrowser(true);
474
                    $this->doDefault($msg);
475
                } else {
476
                    $this->doDefault($lang['strviewdroppedbad']);
477
                }
478
            } else {
479
                $status = $data->dropView($_POST['view'], isset($_POST['cascade']));
480
                if ($status == 0) {
481
                    $this->misc->setReloadBrowser(true);
482
                    $this->doDefault($lang['strviewdropped']);
483
                } else {
484
                    $this->doDefault($lang['strviewdroppedbad']);
485
                }
486
            }
487
        }
488
    }
489
490
    /**
491
     * Sets up choices for table linkage, and which fields to select for the view we're creating
492
     */
493
    public function doSetParamsCreate($msg = '')
494
    {
495
        $conf = $this->conf;
496
        $misc = $this->misc;
497
        $lang = $this->lang;
498
        $data = $misc->getDatabaseAccessor();
499
500
        // Check that they've chosen tables for the view definition
501
        if (!isset($_POST['formTables'])) {
502
            $this->doWizardCreate($lang['strviewneedsdef']);
503
        } else {
504
            // Initialise variables
505
            if (!isset($_REQUEST['formView'])) {
506
                $_REQUEST['formView'] = '';
507
            }
508
509
            if (!isset($_REQUEST['formComment'])) {
510
                $_REQUEST['formComment'] = '';
511
            }
512
513
            $this->printTrail('schema');
514
            $this->printTitle($lang['strcreateviewwiz'], 'pg.view.create');
515
            $this->printMsg($msg);
516
517
            $tblCount = sizeof($_POST['formTables']);
518
            //unserialize our schema/table information and store in arrSelTables
519
            for ($i = 0; $i < $tblCount; $i++) {
520
                $arrSelTables[] = unserialize($_POST['formTables'][$i]);
521
            }
522
523
            $linkCount = $tblCount;
524
525
            //get linking keys
526
            $rsLinkKeys = $data->getLinkingKeys($arrSelTables);
527
            $linkCount  = $rsLinkKeys->recordCount() > $tblCount ? $rsLinkKeys->recordCount() : $tblCount;
528
529
            $arrFields = []; //array that will hold all our table/field names
530
531
            //if we have schemas we need to specify the correct schema for each table we're retrieiving
532
            //with getTableAttributes
533
            $curSchema = $data->_schema;
534
            for ($i = 0; $i < $tblCount; $i++) {
535
                if ($data->_schema != $arrSelTables[$i]['schemaname']) {
536
                    $data->setSchema($arrSelTables[$i]['schemaname']);
537
                }
538
539
                $attrs = $data->getTableAttributes($arrSelTables[$i]['tablename']);
540
                while (!$attrs->EOF) {
541
                    $arrFields["{$arrSelTables[$i]['schemaname']}.{$arrSelTables[$i]['tablename']}.{$attrs->fields['attname']}"] = serialize([
542
                        'schemaname' => $arrSelTables[$i]['schemaname'],
543
                        'tablename'  => $arrSelTables[$i]['tablename'],
544
                        'fieldname'  => $attrs->fields['attname']]
545
                    );
546
                    $attrs->moveNext();
547
                }
548
549
                $data->setSchema($curSchema);
550
            }
551
            asort($arrFields);
552
553
            echo '<form action="' . SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
554
            echo "<table>\n";
555
            echo "<tr><th class=\"data\">{$lang['strviewname']}</th></tr>";
556
            echo "<tr>\n<td class=\"data1\">\n";
557
            // View name
558
            echo '<input name="formView" value="', htmlspecialchars($_REQUEST['formView']), "\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" />\n";
559
            echo "</td>\n</tr>\n";
560
            echo "<tr><th class=\"data\">{$lang['strcomment']}</th></tr>";
561
            echo "<tr>\n<td class=\"data1\">\n";
562
            // View comments
563
            echo '<textarea name="formComment" rows="3" cols="32">',
564
            htmlspecialchars($_REQUEST['formComment']), "</textarea>\n";
565
            echo "</td>\n</tr>\n";
566
            echo "</table>\n";
567
568
            // Output selector for fields to be retrieved from view
569
            echo "<table>\n";
570
            echo "<tr><th class=\"data\">{$lang['strcolumns']}</th></tr>";
571
            echo "<tr>\n<td class=\"data1\">\n";
572
            echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, 'formFields[]', false, '', true);
573
            echo "</td>\n</tr>";
574
            echo "<tr><td><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth1\" value=\"rename\" /><label for=\"dblFldMeth1\">{$lang['strrenamedupfields']}</label>";
575
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth2\" value=\"drop\" /><label for=\"dblFldMeth2\">{$lang['strdropdupfields']}</label>";
576
            echo "<br /><input type=\"radio\" name=\"dblFldMeth\" id=\"dblFldMeth3\" value=\"\" checked=\"checked\" /><label for=\"dblFldMeth3\">{$lang['strerrordupfields']}</label></td></tr></table><br />";
577
578
            // Output the Linking keys combo boxes
579
            echo "<table>\n";
580
            echo "<tr><th class=\"data\">{$lang['strviewlink']}</th></tr>";
581
            $rowClass = 'data1';
582
            for ($i = 0; $i < $linkCount; $i++) {
583
                // Initialise variables
584
                if (!isset($formLink[$i]['operator'])) {
585
                    $formLink[$i]['operator'] = 'INNER JOIN';
586
                }
587
588
                echo "<tr>\n<td class=\"$rowClass\">\n";
589
590
                if (!$rsLinkKeys->EOF) {
591
                    $curLeftLink  = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['p_schema'], 'tablename' => $rsLinkKeys->fields['p_table'], 'fieldname' => $rsLinkKeys->fields['p_field']]));
592
                    $curRightLink = htmlspecialchars(serialize(['schemaname' => $rsLinkKeys->fields['f_schema'], 'tablename' => $rsLinkKeys->fields['f_table'], 'fieldname' => $rsLinkKeys->fields['f_field']]));
593
                    $rsLinkKeys->moveNext();
594
                } else {
595
                    $curLeftLink  = '';
596
                    $curRightLink = '';
597
                }
598
599
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[$i][leftlink]", true, $curLeftLink, false);
600
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($data->joinOps, "formLink[$i][operator]", true, $formLink[$i]['operator']);
601
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formLink[$i][rightlink]", true, $curRightLink, false);
602
                echo "</td>\n</tr>\n";
603
                $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';
604
            }
605
            echo "</table>\n<br />\n";
606
607
            // Build list of available operators (infix only)
608
            $arrOperators = [];
609
            foreach ($data->selectOps as $k => $v) {
610
                if ($v == 'i') {
611
                    $arrOperators[$k] = $k;
612
                }
613
            }
614
615
            // Output additional conditions, note that this portion of the wizard treats the right hand side as literal values
616
            //(not as database objects) so field names will be treated as strings, use the above linking keys section to perform joins
617
            echo "<table>\n";
618
            echo "<tr><th class=\"data\">{$lang['strviewconditions']}</th></tr>";
619
            $rowClass = 'data1';
620
            for ($i = 0; $i < $linkCount; $i++) {
621
                echo "<tr>\n<td class=\"$rowClass\">\n";
622
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrFields, "formCondition[$i][field]");
623
                echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrOperators, "formCondition[$i][operator]", false, false);
624
                echo "<input type=\"text\" name=\"formCondition[$i][txt]\" />\n";
625
                echo "</td>\n</tr>\n";
626
                $rowClass = $rowClass == 'data1' ? 'data2' : 'data1';
627
            }
628
            echo "</table>\n";
629
            echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create_wiz\" />\n";
630
631
            foreach ($arrSelTables as $curTable) {
632
                echo '<input type="hidden" name="formTables[]" value="' . htmlspecialchars(serialize($curTable)) . "\" />\n";
633
            }
634
635
            echo $misc->form;
636
            echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
637
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
638
            echo "</form>\n";
639
        }
640
    }
641
642
    /**
643
     * Display a wizard where they can enter a new view
644
     */
645
    public function doWizardCreate($msg = '')
646
    {
647
        $conf = $this->conf;
648
        $misc = $this->misc;
649
        $lang = $this->lang;
650
        $data = $misc->getDatabaseAccessor();
651
652
        $tables = $data->getTables(true);
653
654
        $this->printTrail('schema');
655
        $this->printTitle($lang['strcreateviewwiz'], 'pg.view.create');
656
        $this->printMsg($msg);
657
658
        echo '<form action="' . SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
659
        echo "<table>\n";
660
        echo "<tr><th class=\"data\">{$lang['strtables']}</th></tr>";
661
        echo "<tr>\n<td class=\"data1\">\n";
662
663
        $arrTables = [];
664
        while (!$tables->EOF) {
665
            $arrTmp                                                                   = [];
666
            $arrTmp['schemaname']                                                     = $tables->fields['nspname'];
667
            $arrTmp['tablename']                                                      = $tables->fields['relname'];
668
            $arrTables[$tables->fields['nspname'] . '.' . $tables->fields['relname']] = serialize($arrTmp);
669
            $tables->moveNext();
670
        }
671
        echo \PHPPgAdmin\XHtml\HTMLController::printCombo($arrTables, 'formTables[]', false, '', true);
672
673
        echo "</td>\n</tr>\n";
674
        echo "</table>\n";
675
        echo "<p><input type=\"hidden\" name=\"action\" value=\"set_params_create\" />\n";
676
        echo $misc->form;
677
        echo "<input type=\"submit\" value=\"{$lang['strnext']}\" />\n";
678
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
679
        echo "</form>\n";
680
    }
681
682
    /**
683
     * Displays a screen where they can enter a new view
684
     */
685
    public function doCreate($msg = '')
686
    {
687
        $conf = $this->conf;
688
        $misc = $this->misc;
689
        $lang = $this->lang;
690
        $data = $misc->getDatabaseAccessor();
691
692
        if (!isset($_REQUEST['formView'])) {
693
            $_REQUEST['formView'] = '';
694
        }
695
696
        if (!isset($_REQUEST['formDefinition'])) {
697
            if (isset($_SESSION['sqlquery'])) {
698
                $_REQUEST['formDefinition'] = $_SESSION['sqlquery'];
699
            } else {
700
                $_REQUEST['formDefinition'] = 'SELECT ';
701
            }
702
        }
703
        if (!isset($_REQUEST['formComment'])) {
704
            $_REQUEST['formComment'] = '';
705
        }
706
707
        $this->printTrail('schema');
708
        $this->printTitle($lang['strcreateview'], 'pg.view.create');
709
        $this->printMsg($msg);
710
711
        echo '<form action="' . SUBFOLDER . "/src/views/views.php\" method=\"post\">\n";
712
        echo "<table style=\"width: 100%\">\n";
713
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strname']}</th>\n";
714
        echo "\t<td class=\"data1\"><input name=\"formView\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
715
        htmlspecialchars($_REQUEST['formView']), "\" /></td>\n\t</tr>\n";
716
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$lang['strdefinition']}</th>\n";
717
        echo "\t<td class=\"data1\"><textarea style=\"width:100%;\" rows=\"10\" cols=\"50\" name=\"formDefinition\">",
718
        htmlspecialchars($_REQUEST['formDefinition']), "</textarea></td>\n\t</tr>\n";
719
        echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strcomment']}</th>\n";
720
        echo "\t\t<td class=\"data1\"><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
721
        htmlspecialchars($_REQUEST['formComment']), "</textarea></td>\n\t</tr>\n";
722
        echo "</table>\n";
723
        echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
724
        echo $misc->form;
725
        echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
726
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
727
        echo "</form>\n";
728
    }
729
730
    /**
731
     * Actually creates the new view in the database
732
     */
733
    public function doSaveCreate()
734
    {
735
        $conf = $this->conf;
736
        $misc = $this->misc;
737
        $lang = $this->lang;
738
        $data = $misc->getDatabaseAccessor();
739
740
        // Check that they've given a name and a definition
741
        if ($_POST['formView'] == '') {
742
            $this->doCreate($lang['strviewneedsname']);
743
        } elseif ($_POST['formDefinition'] == '') {
744
            $this->doCreate($lang['strviewneedsdef']);
745
        } else {
746
            $status = $data->createView($_POST['formView'], $_POST['formDefinition'], false, $_POST['formComment']);
747
            if ($status == 0) {
748
                $this->misc->setReloadBrowser(true);
749
                $this->doDefault($lang['strviewcreated']);
750
            } else {
751
                $this->doCreate($lang['strviewcreatedbad']);
752
            }
753
        }
754
    }
755
756
    /**
757
     * Actually creates the new wizard view in the database
758
     */
759
    public function doSaveCreateWiz()
760
    {
761
        $conf = $this->conf;
762
        $misc = $this->misc;
763
        $lang = $this->lang;
764
        $data = $misc->getDatabaseAccessor();
765
766
        // Check that they've given a name and fields they want to select
767
768
        if (!strlen($_POST['formView'])) {
769
            $this->doSetParamsCreate($lang['strviewneedsname']);
770
        } elseif (!isset($_POST['formFields']) || !count($_POST['formFields'])) {
771
            $this->doSetParamsCreate($lang['strviewneedsfields']);
772
        } else {
773
            $selFields = '';
774
775
            if (!empty($_POST['dblFldMeth'])) {
776
                $tmpHsh = [];
777
            }
778
779
            foreach ($_POST['formFields'] as $curField) {
780
                $arrTmp = unserialize($curField);
781
                $data->fieldArrayClean($arrTmp);
782
                if (!empty($_POST['dblFldMeth'])) {
783
                    // doublon control
784
                    if (empty($tmpHsh[$arrTmp['fieldname']])) {
785
                        // field does not exist
786
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
787
                        $tmpHsh[$arrTmp['fieldname']] = 1;
788
                    } elseif ($_POST['dblFldMeth'] == 'rename') {
789
                        // field exist and must be renamed
790
                        $tmpHsh[$arrTmp['fieldname']]++;
791
                        $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" AS \"{$arrTmp['schemaname']}_{$arrTmp['tablename']}_{$arrTmp['fieldname']}{$tmpHsh[$arrTmp['fieldname']]}\", ";
792
                    }
793
                    /* field already exist, just ignore this one */
794
                } else {
795
                    // no doublon control
796
                    $selFields .= "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\", ";
797
                }
798
            }
799
800
            $selFields = substr($selFields, 0, -2);
801
            unset($arrTmp, $tmpHsh);
802
            $linkFields = '';
803
804
            // If we have links, out put the JOIN ... ON statements
805
            if (is_array($_POST['formLink'])) {
806
                // Filter out invalid/blank entries for our links
807
                $arrLinks = [];
808
                foreach ($_POST['formLink'] as $curLink) {
809
                    if (strlen($curLink['leftlink']) && strlen($curLink['rightlink']) && strlen($curLink['operator'])) {
810
                        $arrLinks[] = $curLink;
811
                    }
812
                }
813
                // We must perform some magic to make sure that we have a valid join order
814
                $count       = sizeof($arrLinks);
815
                $arrJoined   = [];
816
                $arrUsedTbls = [];
817
818
                // If we have at least one join condition, output it
819
                if ($count > 0) {
820
                    $j = 0;
821
                    while ($j < $count) {
822
                        foreach ($arrLinks as $curLink) {
823
                            $arrLeftLink  = unserialize($curLink['leftlink']);
824
                            $arrRightLink = unserialize($curLink['rightlink']);
825
                            $data->fieldArrayClean($arrLeftLink);
826
                            $data->fieldArrayClean($arrRightLink);
827
828
                            $tbl1 = "\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\"";
829
                            $tbl2 = "\"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\"";
830
831
                            if ((!in_array($curLink, $arrJoined) && in_array($tbl1, $arrUsedTbls)) || !count($arrJoined)) {
832
833
                                // Make sure for multi-column foreign keys that we use a table alias tables joined to more than once
834
                                // This can (and should be) more optimized for multi-column foreign keys
835
                                $adj_tbl2 = in_array($tbl2, $arrUsedTbls) ? "$tbl2 AS alias_ppa_" . mktime() : $tbl2;
836
837
                                $linkFields .= strlen($linkFields) ? "{$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") "
838
                                : "$tbl1 {$curLink['operator']} $adj_tbl2 ON (\"{$arrLeftLink['schemaname']}\".\"{$arrLeftLink['tablename']}\".\"{$arrLeftLink['fieldname']}\" = \"{$arrRightLink['schemaname']}\".\"{$arrRightLink['tablename']}\".\"{$arrRightLink['fieldname']}\") ";
839
840
                                $arrJoined[] = $curLink;
841
                                if (!in_array($tbl1, $arrUsedTbls)) {
842
                                    $arrUsedTbls[] = $tbl1;
843
                                }
844
845
                                if (!in_array($tbl2, $arrUsedTbls)) {
846
                                    $arrUsedTbls[] = $tbl2;
847
                                }
848
                            }
849
                        }
850
                        $j++;
851
                    }
852
                }
853
            }
854
855
            //if linkfields has no length then either _POST['formLink'] was not set, or there were no join conditions
856
            //just select from all seleted tables - a cartesian join do a
857
            if (!strlen($linkFields)) {
858
                foreach ($_POST['formTables'] as $curTable) {
859
                    $arrTmp = unserialize($curTable);
860
                    $data->fieldArrayClean($arrTmp);
861
                    $linkFields .= strlen($linkFields) ? ", \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"" : "\"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\"";
862
                }
863
            }
864
865
            $addConditions = '';
866
            if (is_array($_POST['formCondition'])) {
867
                foreach ($_POST['formCondition'] as $curCondition) {
868
                    if (strlen($curCondition['field']) && strlen($curCondition['txt'])) {
869
                        $arrTmp = unserialize($curCondition['field']);
870
                        $data->fieldArrayClean($arrTmp);
871
                        $addConditions .= strlen($addConditions) ? " AND \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' "
872
                        : " \"{$arrTmp['schemaname']}\".\"{$arrTmp['tablename']}\".\"{$arrTmp['fieldname']}\" {$curCondition['operator']} '{$curCondition['txt']}' ";
873
                    }
874
                }
875
            }
876
877
            $viewQuery = "SELECT $selFields FROM $linkFields ";
878
879
            //add where from additional conditions
880
            if (strlen($addConditions)) {
881
                $viewQuery .= ' WHERE ' . $addConditions;
882
            }
883
884
            $status = $data->createView($_POST['formView'], $viewQuery, false, $_POST['formComment']);
885
            if ($status == 0) {
886
                $this->misc->setReloadBrowser(true);
887
                $this->doDefault($lang['strviewcreated']);
888
            } else {
889
                $this->doSetParamsCreate($lang['strviewcreatedbad']);
890
            }
891
        }
892
    }
893
}
894