Passed
Push — develop ( 19961b...779af6 )
by Felipe
04:58
created

ViewsController::doSaveCreate()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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