Passed
Pull Request — develop (#210)
by
unknown
08:24
created

FunctionsController::showDefinition()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 47
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 47
rs 9.472
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.49
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 FunctionsController extends BaseController
17
{
18
    public $table_place      = 'functions-functions';
19
    public $controller_title = 'strfunctions';
20
21
    /**
22
     * Default method to render the controller according to the action parameter.
23
     */
24
    public function render()
25
    {
26
        if ('tree' == $this->action) {
27
            return $this->doTree();
28
        }
29
30
        $header_template = 'header_datatables.twig';
31
        $footer_template = 'footer.twig';
32
        ob_start();
33
        switch ($this->action) {
34
            case 'save_create':
35
                if (isset($_POST['cancel'])) {
36
                    $this->doDefault();
37
                } else {
38
                    $this->doSaveCreate();
39
                }
40
41
                break;
42
            case 'create':
43
                $header_template = 'header_select2.twig';
44
                $this->doCreate();
45
46
                break;
47
            case 'drop':
48
                if (isset($_POST['drop'])) {
49
                    $this->doDrop(false);
50
                } else {
51
                    $this->doDefault();
52
                }
53
54
                break;
55
            case 'confirm_drop':
56
                $this->doDrop(true);
57
58
                break;
59
            case 'save_edit':
60
                if (isset($_POST['cancel'])) {
61
                    $this->doDefault();
62
                } else {
63
                    $this->doSaveEdit();
64
                }
65
66
                break;
67
            case 'edit':
68
                $header_template = 'header_sqledit.twig';
69
                $footer_template = 'footer_sqledit.twig';
70
                $this->doEdit();
71
72
                break;
73
            case 'properties':
74
                $header_template = 'header_highlight.twig';
75
                $this->doProperties();
76
77
                break;
78
            case 'show':
79
                if (isset($_GET['function'], $_GET['function_oid'])) {
80
                    $header_template = 'header_highlight.twig';
81
                    $this->showDefinition();
0 ignored issues
show
Bug introduced by
The call to PHPPgAdmin\Controller\Fu...oller::showDefinition() has too few arguments starting with fname. ( Ignorable by Annotation )

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

81
                    $this->/** @scrutinizer ignore-call */ 
82
                           showDefinition();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
82
                } else {
83
                    $this->doDefault();
84
                }
85
86
                break;
87
            default:
88
                $this->doDefault();
89
90
                break;
91
        }
92
        $output = ob_get_clean();
93
94
        $this->printHeader($this->headerTitle(), null, true, $header_template);
95
        $this->printBody();
96
        echo $output;
97
        $this->printFooter(true, $footer_template);
98
    }
99
100
    /**
101
     * Show default list of functions in the database.
102
     *
103
     * @param mixed $msg
104
     */
105
    public function doDefault($msg = '')
106
    {
107
        $data = $this->misc->getDatabaseAccessor();
108
109
        $this->printTrail('schema');
110
        $this->printTabs('schema', 'functions');
111
        $this->printMsg($msg);
112
113
        $funcs = $data->getFunctions();
114
115
        $columns = [
116
            'function'     => [
117
                'title' => $this->lang['strfunction'],
118
                'field' => Decorator::field('proproto'),
119
                'url'   => \SUBFOLDER."/redirect/function?action=properties&amp;{$this->misc->href}&amp;",
120
                'vars'  => ['function' => 'proproto', 'function_oid' => 'prooid'],
121
            ],
122
            'returns'      => [
123
                'title' => $this->lang['strreturns'],
124
                'field' => Decorator::field('proreturns'),
125
            ],
126
            'owner'        => [
127
                'title' => $this->lang['strowner'],
128
                'field' => Decorator::field('proowner'),
129
            ],
130
            'proglanguage' => [
131
                'title' => $this->lang['strproglanguage'],
132
                'field' => Decorator::field('prolanguage'),
133
            ],
134
            'actions'      => [
135
                'title' => $this->lang['stractions'],
136
            ],
137
            'comment'      => [
138
                'title' => $this->lang['strcomment'],
139
                'field' => Decorator::field('procomment'),
140
            ],
141
        ];
142
143
        $actions = [
144
            'multiactions' => [
145
                'keycols' => ['function' => 'proproto', 'function_oid' => 'prooid'],
146
                'url'     => 'functions',
147
            ],
148
            'alter'        => [
149
                'content' => $this->lang['stralter'],
150
                'attr'    => [
151
                    'href' => [
152
                        'url'     => 'functions',
153
                        'urlvars' => [
154
                            'action'       => 'edit',
155
                            'function'     => Decorator::field('proproto'),
156
                            'function_oid' => Decorator::field('prooid'),
157
                        ],
158
                    ],
159
                ],
160
            ],
161
            'drop'         => [
162
                'multiaction' => 'confirm_drop',
163
                'content'     => $this->lang['strdrop'],
164
                'attr'        => [
165
                    'href' => [
166
                        'url'     => 'functions',
167
                        'urlvars' => [
168
                            'action'       => 'confirm_drop',
169
                            'function'     => Decorator::field('proproto'),
170
                            'function_oid' => Decorator::field('prooid'),
171
                        ],
172
                    ],
173
                ],
174
            ],
175
            'privileges'   => [
176
                'content' => $this->lang['strprivileges'],
177
                'attr'    => [
178
                    'href' => [
179
                        'url'     => 'privileges',
180
                        'urlvars' => [
181
                            'subject'      => 'function',
182
                            'function'     => Decorator::field('proproto'),
183
                            'function_oid' => Decorator::field('prooid'),
184
                        ],
185
                    ],
186
                ],
187
            ],
188
        ];
189
190
        echo $this->printTable($funcs, $columns, $actions, $this->table_place, $this->lang['strnofunctions']);
191
192
        $this->_printNavLinks('functions-functions');
193
    }
194
195
    private function _printNavLinks($place, $func_full = '')
196
    {
197
        if ($place === 'functions-properties') {
198
            $navlinks = [
199
                'showall' => [
200
                    'attr'    => [
201
                        'href' => [
202
                            'url'     => 'functions',
203
                            'urlvars' => [
204
                                'server'   => $_REQUEST['server'],
205
                                'database' => $_REQUEST['database'],
206
                                'schema'   => $_REQUEST['schema'],
207
                            ],
208
                        ],
209
                    ],
210
                    'content' => $this->lang['strshowallfunctions'],
211
                ],
212
                'alter'   => [
213
                    'attr'    => [
214
                        'href' => [
215
                            'url'     => 'functions',
216
                            'urlvars' => [
217
                                'action'       => 'edit',
218
                                'server'       => $_REQUEST['server'],
219
                                'database'     => $_REQUEST['database'],
220
                                'schema'       => $_REQUEST['schema'],
221
                                'function'     => $_REQUEST['function'],
222
                                'function_oid' => $_REQUEST['function_oid'],
223
                            ],
224
                        ],
225
                    ],
226
                    'content' => $this->lang['stralter'],
227
                ],
228
                'drop'    => [
229
                    'attr'    => [
230
                        'href' => [
231
                            'url'     => 'functions',
232
                            'urlvars' => [
233
                                'action'       => 'confirm_drop',
234
                                'server'       => $_REQUEST['server'],
235
                                'database'     => $_REQUEST['database'],
236
                                'schema'       => $_REQUEST['schema'],
237
                                'function'     => $func_full,
238
                                'function_oid' => $_REQUEST['function_oid'],
239
                            ],
240
                        ],
241
                    ],
242
                    'content' => $this->lang['strdrop'],
243
                ],
244
            ];
245
        } elseif ($place === 'functions-functions') {
246
            $navlinks = [
247
                'createpl'       => [
248
                    'attr'    => [
249
                        'href' => [
250
                            'url'     => 'functions',
251
                            'urlvars' => [
252
                                'action'   => 'create',
253
                                'server'   => $_REQUEST['server'],
254
                                'database' => $_REQUEST['database'],
255
                                'schema'   => $_REQUEST['schema'],
256
                            ],
257
                        ],
258
                    ],
259
                    'content' => $this->lang['strcreateplfunction'],
260
                ],
261
                'createinternal' => [
262
                    'attr'    => [
263
                        'href' => [
264
                            'url'     => 'functions',
265
                            'urlvars' => [
266
                                'action'   => 'create',
267
                                'language' => 'internal',
268
                                'server'   => $_REQUEST['server'],
269
                                'database' => $_REQUEST['database'],
270
                                'schema'   => $_REQUEST['schema'],
271
                            ],
272
                        ],
273
                    ],
274
                    'content' => $this->lang['strcreateinternalfunction'],
275
                ],
276
                'createc'        => [
277
                    'attr'    => [
278
                        'href' => [
279
                            'url'     => 'functions',
280
                            'urlvars' => [
281
                                'action'   => 'create',
282
                                'language' => 'C',
283
                                'server'   => $_REQUEST['server'],
284
                                'database' => $_REQUEST['database'],
285
                                'schema'   => $_REQUEST['schema'],
286
                            ],
287
                        ],
288
                    ],
289
                    'content' => $this->lang['strcreatecfunction'],
290
                ],
291
            ];
292
        } else {
293
            return;
294
        }
295
296
        $this->printNavLinks($navlinks, $place, get_defined_vars());
297
    }
298
299
    /**
300
     * Generate XML for the browser tree.
301
     */
302
    public function doTree()
303
    {
304
        $data = $this->misc->getDatabaseAccessor();
305
306
        $funcs = $data->getFunctions();
307
308
        $proto = Decorator::concat(Decorator::field('proname'), ' (', Decorator::field('proarguments'), ')');
309
310
        $reqvars = $this->misc->getRequestVars('function');
311
312
        $attrs = [
313
            'text'    => $proto,
314
            'icon'    => 'Function',
315
            'toolTip' => Decorator::field('procomment'),
316
            'action'  => Decorator::redirecturl(
317
                'redirect',
318
                $reqvars,
319
                [
320
                    'action'       => 'properties',
321
                    'function'     => $proto,
322
                    'function_oid' => Decorator::field('prooid'),
323
                ]
324
            ),
325
        ];
326
327
        return $this->printTree($funcs, $attrs, 'functions');
328
    }
329
330
    /**
331
     * Function to save after editing a function.
332
     */
333
    public function doSaveEdit()
334
    {
335
        $data = $this->misc->getDatabaseAccessor();
336
337
        $fnlang = strtolower($_POST['original_lang']);
338
339
        if ('c' == $fnlang) {
340
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
341
        } elseif ('internal' == $fnlang) {
342
            $def = $_POST['formLinkSymbol'];
343
        } else {
344
            $def = $_POST['formDefinition'];
345
        }
346
        if (!$data->hasFunctionAlterSchema()) {
347
            $_POST['formFuncSchema'] = '';
348
        }
349
350
        $status = $data->setFunction(
351
            $_POST['original_function'],
352
            $_POST['formFunction'],
353
            $_POST['original_arguments'],
354
            $_POST['original_returns'],
355
            $def,
356
            $_POST['original_lang'],
357
            $_POST['formProperties'],
358
            isset($_POST['original_setof']),
359
            $_POST['original_owner'],
360
            $_POST['formFuncOwn'],
361
            $_POST['original_schema'],
362
            $_POST['formFuncSchema'],
363
            isset($_POST['formCost']) ? $_POST['formCost'] : null,
364
            isset($_POST['formRows']) ? $_POST['formRows'] : 0,
365
            $_POST['formComment']
366
        );
367
368
        if (0 == $status) {
369
            // If function has had schema altered, need to change to the new schema
370
            // and reload the browser frame.
371
            if (!empty($_POST['formFuncSchema']) && ($_POST['formFuncSchema'] != $_POST['original_schema'])) {
372
                // Jump them to the new function schema
373
                $this->misc->setCurrentSchema($_POST['formFuncSchema']);
374
                // Force a browser reload
375
                $this->misc->setReloadBrowser(true);
376
            }
377
            $this->doProperties($this->lang['strfunctionupdated']);
378
        } else {
379
            $this->doEdit($this->lang['strfunctionupdatedbad']);
380
        }
381
    }
382
383
    private function _getNamedParamsArgs($data, $fndata)
384
    {
385
        if (isset($fndata->fields['proallarguments'])) {
386
            $args_arr = $data->phpArray($fndata->fields['proallarguments']);
387
        } else {
388
            $args_arr = explode(', ', $fndata->fields['proarguments']);
389
        }
390
        $names_arr     = $data->phpArray($fndata->fields['proargnames']);
391
        $modes_arr     = $data->phpArray($fndata->fields['proargmodes']);
392
        $args          = '';
393
        $args_arr_size = sizeof($args_arr);
394
        for ($i = 0; $i < $args_arr_size; ++$i) {
395
            if (0 != $i) {
396
                $args .= ', ';
397
            }
398
399
            if (isset($modes_arr[$i])) {
400
                switch ($modes_arr[$i]) {
401
                    case 'i':
402
                        $args .= ' IN ';
403
404
                        break;
405
                    case 'o':
406
                        $args .= ' OUT ';
407
408
                        break;
409
                    case 'b':
410
                        $args .= ' INOUT ';
411
412
                        break;
413
                    case 'v':
414
                        $args .= ' VARIADIC ';
415
416
                        break;
417
                    case 't':
418
                        $args .= ' TABLE ';
419
420
                        break;
421
                }
422
            }
423
            if (isset($names_arr[$i]) && '' != $names_arr[$i]) {
424
                $data->fieldClean($names_arr[$i]);
425
                $args .= '"'.$names_arr[$i].'" ';
426
            }
427
            $args .= $args_arr[$i];
428
        }
429
430
        return $args;
431
    }
432
433
    /**
434
     * Function to allow editing of a Function.
435
     *
436
     * @param mixed $msg
437
     */
438
    public function doEdit($msg = '')
439
    {
440
        $data = $this->misc->getDatabaseAccessor();
441
442
        $this->printTrail('function');
443
        $this->printTabs('function', 'definition');
444
        $this->printTitle($this->lang['stralter'], 'pg.function.alter');
445
        $this->printMsg($msg);
446
447
        $fndata = $data->getFunction($_REQUEST['function_oid']);
448
449
        if ($fndata->recordCount() <= 0) {
450
            echo "<p>{$this->lang['strnodata']}</p>".PHP_EOL;
451
452
            return;
453
        }
454
        $fndata->fields['proretset'] = $data->phpBool($fndata->fields['proretset']);
455
456
        // Initialise variables
457
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', $fndata->fields['prosrc']);
458
459
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->getFunctionProperties($fndata->fields));
460
461
        $_POST['formFunction'] = $this->getPostParam('formFunction', $fndata->fields['proname']);
462
463
        $_POST['formComment'] = $this->getPostParam('formComment', $fndata->fields['procomment']);
464
465
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', $fndata->fields['probin']);
466
467
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', $fndata->fields['prosrc']);
468
469
        $_POST['formFuncOwn'] = $this->getPostParam('formFuncOwn', $fndata->fields['proowner']);
470
471
        $_POST['formFuncSchema'] = $this->getPostParam('formFuncSchema', $fndata->fields['proschema']);
472
473
        if ($data->hasFunctionCosting()) {
474
            $_POST['formCost'] = $this->getPostParam('formCost', $fndata->fields['procost']);
475
476
            $_POST['formRows'] = $this->getPostParam('formRows', $fndata->fields['prorows']);
477
        }
478
479
        // Deal with named parameters
480
        if ($data->hasNamedParams()) {
481
            $args = $this->_getNamedParamsArgs($data, $fndata);
482
        } else {
483
            $args = $fndata->fields['proarguments'];
484
        }
485
486
        echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
487
        echo '<table style="width: 95%">'.PHP_EOL;
488
        echo '<tr>'.PHP_EOL;
489
        echo "<th class=\"data required\">{$this->lang['strschema']}</th>".PHP_EOL;
490
        echo "<th class=\"data required\">{$this->lang['strfunction']}</th>".PHP_EOL;
491
        echo "<th class=\"data\">{$this->lang['strarguments']}</th>".PHP_EOL;
492
        echo "<th class=\"data required\">{$this->lang['strreturns']}</th>".PHP_EOL;
493
        echo "<th class=\"data required\">{$this->lang['strproglanguage']}</th>".PHP_EOL;
494
        echo '</tr>'.PHP_EOL;
495
496
        echo '<tr>'.PHP_EOL;
497
        echo '<td class="data1">';
498
        echo '<input type="hidden" name="original_schema" value="', htmlspecialchars($fndata->fields['proschema']), '" />'.PHP_EOL;
499
        if ($data->hasFunctionAlterSchema()) {
500
            $schemas = $data->getSchemas();
501
            echo '<select name="formFuncSchema">';
502
            while (!$schemas->EOF) {
503
                $schema = $schemas->fields['nspname'];
504
                echo '<option value="', htmlspecialchars($schema), '"',
505
                ($schema == $_POST['formFuncSchema']) ? ' selected="selected"' : '', '>', htmlspecialchars($schema), '</option>'.PHP_EOL;
506
                $schemas->moveNext();
507
            }
508
            echo '</select>'.PHP_EOL;
509
        } else {
510
            echo $fndata->fields['proschema'];
511
        }
512
513
        echo '</td>'.PHP_EOL;
514
        echo '<td class="data1">';
515
        echo '<input type="hidden" name="original_function" value="', htmlspecialchars($fndata->fields['proname']), '" />'.PHP_EOL;
516
        echo "<input name=\"formFunction\" style=\"width: 100%; box-sizing: border-box;\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_POST['formFunction']), '" />';
517
        echo '</td>'.PHP_EOL;
518
519
        echo '<td class="data1">', $this->misc->printVal($args), PHP_EOL;
520
        echo '<input type="hidden" name="original_arguments" value="', htmlspecialchars($args), '" />'.PHP_EOL;
521
        echo '</td>'.PHP_EOL;
522
523
        echo '<td class="data1">';
524
        if ($fndata->fields['proretset']) {
525
            echo 'setof ';
526
        }
527
528
        echo $this->misc->printVal($fndata->fields['proresult']), PHP_EOL;
529
        echo '<input type="hidden" name="original_returns" value="', htmlspecialchars($fndata->fields['proresult']), '" />'.PHP_EOL;
530
        if ($fndata->fields['proretset']) {
531
            echo '<input type="hidden" name="original_setof" value="yes" />'.PHP_EOL;
532
        }
533
534
        echo '</td>'.PHP_EOL;
535
536
        echo '<td class="data1">', $this->misc->printVal($fndata->fields['prolanguage']), PHP_EOL;
537
        echo '<input type="hidden" name="original_lang" value="', htmlspecialchars($fndata->fields['prolanguage']), '" />'.PHP_EOL;
538
        echo '</td>'.PHP_EOL;
539
        echo '</tr>'.PHP_EOL;
540
541
        $fnlang = strtolower($fndata->fields['prolanguage']);
542
        if ('c' == $fnlang) {
543
            echo "<tr><th class=\"data required\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
544
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
545
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
546
            htmlspecialchars($_POST['formObjectFile']), '" /></td>'.PHP_EOL;
547
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
548
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
549
        } elseif ('internal' == $fnlang) {
550
            echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
551
            echo '<tr><td class="data1" colspan="5"><input type="text" name="formLinkSymbol" style="width:100%" value="',
552
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
553
        } else {
554
            echo "<tr><th class=\"data required\" colspan=\"5\">{$this->lang['strdefinition']}</th></tr>".PHP_EOL;
555
            echo '<tr><td class="data1" colspan="5">';
556
            $textarea_id = ($fnlang === 'sql' || $fnlang === 'plpgsql') ? 'query' : 'formDefinition';
557
            echo '<textarea style="width:100%;" rows="20" cols="50" id="'.$textarea_id.'" name="formDefinition">';
558
            echo htmlspecialchars($_POST['formDefinition']);
559
            echo '</textarea></td></tr>'.PHP_EOL;
560
        }
561
562
        // Display function comment
563
        echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strcomment']}</th></tr>".PHP_EOL;
564
        echo '<tr><td class="data1" colspan="5">';
565
        echo '<textarea style="width:100%;" name="formComment" rows="3" cols="50">';
566
        echo htmlspecialchars($_POST['formComment']);
567
        echo '</textarea></td></tr>'.PHP_EOL;
568
569
        // Display function cost options
570
        if ($data->hasFunctionCosting()) {
571
            echo "<tr><th class=\"data required\" colspan=\"5\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
572
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
573
            htmlspecialchars($_POST['formCost']).'" /></td>';
574
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"",
575
            htmlspecialchars($_POST['formRows']), '"', (!$fndata->fields['proretset']) ? 'disabled' : '', '/></td>';
576
        }
577
578
        // Display function properties
579
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
580
            echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
581
            echo '<tr><td class="data1" colspan="5">'.PHP_EOL;
582
            $i = 0;
583
            foreach ($data->funcprops as $k => $v) {
584
                echo "<select name=\"formProperties[{$i}]\">".PHP_EOL;
585
                foreach ($v as $p) {
586
                    echo '<option value="', htmlspecialchars($p), '"',
587
                    ($_POST['formProperties'][$i] == $p) ? ' selected="selected"' : '',
588
                    '>', $this->misc->printVal($p), '</option>'.PHP_EOL;
589
                }
590
                echo '</select><br />'.PHP_EOL;
591
                ++$i;
592
            }
593
            echo '</td></tr>'.PHP_EOL;
594
        }
595
596
        // function owner
597
        if ($data->hasFunctionAlterOwner()) {
598
            $users = $data->getUsers();
599
            echo "<tr><td class=\"data1\" colspan=\"5\">{$this->lang['strowner']}: <select name=\"formFuncOwn\">";
600
            while (!$users->EOF) {
601
                $uname = $users->fields['usename'];
602
                echo '<option value="', htmlspecialchars($uname), '"',
603
                ($uname == $_POST['formFuncOwn']) ? ' selected="selected"' : '', '>', htmlspecialchars($uname), '</option>'.PHP_EOL;
604
                $users->moveNext();
605
            }
606
            echo '</select>'.PHP_EOL;
607
            echo '<input type="hidden" name="original_owner" value="', htmlspecialchars($fndata->fields['proowner']), '" />'.PHP_EOL;
608
            echo '</td></tr>'.PHP_EOL;
609
        }
610
        echo '</table>'.PHP_EOL;
611
        echo '<p><input type="hidden" name="action" value="save_edit" />'.PHP_EOL;
612
        echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), '" />'.PHP_EOL;
613
        echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), '" />'.PHP_EOL;
614
        echo $this->misc->form;
615
        echo "<input type=\"submit\" value=\"{$this->lang['stralter']}\" />".PHP_EOL;
616
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
617
        echo '</form>'.PHP_EOL;
618
    }
619
620
    /**
621
     * Show the creation sentence for this function.
622
     *
623
     * @param string $fname        The function name
624
     * @param int    $function_oid The function oid
625
     *
626
     * @return string the navlinks to print at the bottom
627
     */
628
    public function showDefinition($fname, $function_oid)
0 ignored issues
show
Unused Code introduced by
The parameter $fname is not used and could be removed. ( Ignorable by Annotation )

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

628
    public function showDefinition(/** @scrutinizer ignore-unused */ $fname, $function_oid)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
629
    {
630
        $data = $this->misc->getDatabaseAccessor();
631
632
        $this->printTrail('function');
633
        $this->printTabs('function', 'export');
634
        $this->printTitle($this->lang['strproperties'], 'pg.function');
635
636
        $fname     = str_replace(' ', '', $f);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $f seems to be never defined.
Loading history...
637
        $funcdata  = $data->getFunctionDef($function_oid);
638
        $func_full = '';
639
        if ($funcdata->recordCount() <= 0) {
640
            echo "<p>{$this->lang['strnodata']}</p>".PHP_EOL;
641
642
            return $this->_printNavLinks('functions-properties', $func_full);
643
        }
644
645
        echo '<table style="width: 95%">'.PHP_EOL;
646
647
        $fnlang = strtolower($funcdata->fields['prolanguage']);
0 ignored issues
show
Unused Code introduced by
The assignment to $fnlang is dead and can be removed.
Loading history...
648
        echo '<tr><td class="data1" colspan="4">';
649
        echo sprintf('<pre><code class="sql hljs">%s', PHP_EOL);
650
651
        echo sprintf('%s--%s', PHP_EOL, PHP_EOL);
652
        echo sprintf('-- Name: %s; Type: FUNCTION; Schema: %s; Owner: %s', $fname, $funcdata->fields['nspname'], $funcdata->fields['relowner']);
653
        echo sprintf('%s--%s%s', PHP_EOL, PHP_EOL, PHP_EOL);
654
655
        echo sprintf('%s;', $funcdata->fields['pg_get_functiondef']);
656
657
        echo sprintf('%s%sALTER FUNCTION %s OWNER TO %s;%s', PHP_EOL, PHP_EOL, $fname, $funcdata->fields['relowner'], PHP_EOL);
658
659
        // Show comment if any
660
        if (null !== $funcdata->fields['relcomment']) {
661
            echo sprintf('%s--%s', PHP_EOL, PHP_EOL);
662
            echo sprintf('-- Name: %s; Type: COMMENT; Schema: %s; Owner: %s', $fname, $funcdata->fields['nspname'], $funcdata->fields['relowner']);
663
            echo sprintf('%s--%s%s', PHP_EOL, PHP_EOL, PHP_EOL);
664
            echo sprintf("%sCOMMENT ON FUNCTION %s.%s IS '%s';%s", PHP_EOL, $funcdata->fields['nspname'], $fname, $funcdata->fields['relcomment'], PHP_EOL);
665
            //echo '<p class="comment">', $this->misc->printVal($funcdata->fields['relcomment']), '</p>' . PHP_EOL;
666
        }
667
668
        echo sprintf('%s</code></pre>', PHP_EOL);
669
670
        echo '</td></tr>'.PHP_EOL;
671
672
        echo '</table>'.PHP_EOL;
673
674
        return $this->_printNavLinks('functions-properties', $func_full);
675
    }
676
677
    /**
678
     * Show read only properties of a function.
679
     *
680
     * @param mixed $msg
681
     */
682
    public function doProperties($msg = '')
683
    {
684
        $data = $this->misc->getDatabaseAccessor();
685
686
        $this->printTrail('function');
687
        $this->printTabs('function', 'definition');
688
        $this->printTitle($this->lang['strproperties'], 'pg.function');
689
        $this->printMsg($msg);
690
691
        $funcdata  = $data->getFunction($_REQUEST['function_oid']);
692
        $func_full = '';
693
        if ($funcdata->recordCount() <= 0) {
694
            echo "<p>{$this->lang['strnodata']}</p>".PHP_EOL;
695
696
            return $this->_printNavLinks('functions-properties', $func_full);
697
        }
698
        // Deal with named parameters
699
        $args = $this->_getPropertiesArgs($funcdata);
700
701
        // Show comment if any
702
        if (null !== $funcdata->fields['procomment']) {
703
            echo '<p class="comment">', $this->misc->printVal($funcdata->fields['procomment']), '</p>'.PHP_EOL;
704
        }
705
706
        $funcdata->fields['proretset'] = $data->phpBool($funcdata->fields['proretset']);
707
        $func_full                     = $funcdata->fields['proname'].'('.$funcdata->fields['proarguments'].')';
708
709
        echo '<table style="width: 95%">'.PHP_EOL;
710
711
        echo sprintf('<tr><th class="data">%s</th>%s', $this->lang['strfunction'], PHP_EOL);
712
        echo sprintf('<th class="data">%s</th>%s', $this->lang['strarguments'], PHP_EOL);
713
        echo sprintf('<th class="data">%s</th>%s', $this->lang['strreturns'], PHP_EOL);
714
        echo sprintf('<th class="data">%s</th></tr>%s', $this->lang['strproglanguage'], PHP_EOL);
715
716
        echo '<tr><td class="data1">', $this->misc->printVal($funcdata->fields['proname']), '</td>'.PHP_EOL;
717
        echo '<td class="data1">', $this->misc->printVal($args), '</td>'.PHP_EOL;
718
        echo '<td class="data1">';
719
        if ($funcdata->fields['proretset']) {
720
            echo 'setof ';
721
        }
722
723
        echo $this->misc->printVal($funcdata->fields['proresult']), '</td>'.PHP_EOL;
724
        echo '<td class="data1">', $this->misc->printVal($funcdata->fields['prolanguage']), '</td></tr>'.PHP_EOL;
725
726
        $fnlang = strtolower($funcdata->fields['prolanguage']);
727
        if ('c' == $fnlang) {
728
            echo "<tr><th class=\"data\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
729
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
730
            echo '<tr><td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['probin']), '</td>'.PHP_EOL;
731
            echo '<td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>'.PHP_EOL;
732
        } elseif ('internal' == $fnlang) {
733
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
734
            echo '<tr><td class="data1" colspan="4">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>'.PHP_EOL;
735
        } else {
736
            echo '<tr><td class="data1" colspan="4">';
737
            echo sprintf('<pre><code class="%s hljs">%s</code></pre>', $fnlang, $funcdata->fields['prosrc']);
738
            echo '</td></tr>'.PHP_EOL;
739
        }
740
741
        // Display function cost options
742
        if ($data->hasFunctionCosting()) {
743
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
744
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: ", $this->misc->printVal($funcdata->fields['procost']), ' </td>';
745
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: ", $this->misc->printVal($funcdata->fields['prorows']), ' </td>';
746
        }
747
748
        // Show flags
749
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
750
            // Fetch an array of the function properties
751
            $funcprops = $data->getFunctionProperties($funcdata->fields);
752
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
753
            echo '<tr><td class="data1" colspan="4">'.PHP_EOL;
754
            foreach ($funcprops as $v) {
755
                echo $this->misc->printVal($v), '<br />'.PHP_EOL;
756
            }
757
            echo '</td></tr>'.PHP_EOL;
758
        }
759
760
        echo "<tr><td class=\"data1\" colspan=\"5\">{$this->lang['strowner']}: ", htmlspecialchars($funcdata->fields['proowner']), PHP_EOL;
761
        echo '</td></tr>'.PHP_EOL;
762
        echo '</table>'.PHP_EOL;
763
764
        return $this->_printNavLinks('functions-properties', $func_full);
765
    }
766
767
    /**
768
     * Show confirmation of drop and perform actual drop.
769
     *
770
     * @param mixed $confirm
771
     */
772
    public function doDrop($confirm)
773
    {
774
        $data = $this->misc->getDatabaseAccessor();
775
776
        if (empty($_REQUEST['function']) && empty($_REQUEST['ma'])) {
777
            return $this->doDefault($this->lang['strspecifyfunctiontodrop']);
778
        }
779
780
        if ($confirm) {
781
            $this->printTrail('function');
782
            $this->printTabs('function', 'definition');
783
            $this->printTitle($this->lang['strdrop'], 'pg.function.drop');
784
785
            echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
786
787
            //If multi drop
788
            if (isset($_REQUEST['ma'])) {
789
                foreach ($_REQUEST['ma'] as $v) {
790
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
791
                    echo '<p>', sprintf($this->lang['strconfdropfunction'], $this->misc->printVal($a['function'])), '</p>'.PHP_EOL;
792
                    echo '<input type="hidden" name="function[]" value="', htmlspecialchars($a['function']), '" />'.PHP_EOL;
793
                    echo '<input type="hidden" name="function_oid[]" value="', htmlspecialchars($a['function_oid']), '" />'.PHP_EOL;
794
                }
795
            } else {
796
                echo '<p>', sprintf($this->lang['strconfdropfunction'], $this->misc->printVal($_REQUEST['function'])), '</p>'.PHP_EOL;
797
                echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), '" />'.PHP_EOL;
798
                echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), '" />'.PHP_EOL;
799
            }
800
801
            echo '<input type="hidden" name="action" value="drop" />'.PHP_EOL;
802
803
            echo $this->misc->form;
804
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /><label for=\"cascade\">{$this->lang['strcascade']}</label></p>".PHP_EOL;
805
            echo "<input type=\"submit\" name=\"drop\" value=\"{$this->lang['strdrop']}\" />".PHP_EOL;
806
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />".PHP_EOL;
807
            echo '</form>'.PHP_EOL;
808
        } else {
809
            if (is_array($_POST['function_oid'])) {
810
                $msg    = '';
811
                $status = $data->beginTransaction();
812
                if (0 == $status) {
813
                    foreach ($_POST['function_oid'] as $k => $s) {
814
                        $status = $data->dropFunction($s, isset($_POST['cascade']));
815
                        if (0 == $status) {
816
                            $msg .= sprintf('%s: %s<br />', htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $this->lang['strfunctiondropped']);
817
                        } else {
818
                            $data->endTransaction();
819
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $this->lang['strfunctiondroppedbad']));
820
821
                            return;
822
                        }
823
                    }
824
                }
825
                if (0 == $data->endTransaction()) {
826
                    // Everything went fine, back to the Default page....
827
                    $this->misc->setReloadBrowser(true);
828
                    $this->doDefault($msg);
829
                } else {
830
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
831
                }
832
            } else {
833
                $status = $data->dropFunction($_POST['function_oid'], isset($_POST['cascade']));
834
                if (0 == $status) {
835
                    $this->misc->setReloadBrowser(true);
836
                    $this->doDefault($this->lang['strfunctiondropped']);
837
                } else {
838
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
839
                }
840
            }
841
        }
842
    }
843
844
    /**
845
     * Displays a screen where they can enter a new function.
846
     *
847
     * @param string $msg  message to display
848
     * @param mixed  $szJS
849
     */
850
    public function doCreate($msg = '', $szJS = '')
851
    {
852
        $data = $this->misc->getDatabaseAccessor();
853
854
        $this->printTrail('schema');
855
        $_POST['formFunction'] = $this->getPostParam('formFunction', '');
856
857
        $_POST['formArguments'] = $this->getPostParam('formArguments', '');
858
859
        $_POST['formReturns'] = $this->getPostParam('formReturns', '');
860
861
        $this->coalesceArr($_POST, 'formLanguage', isset($_REQUEST['language']) ? $_REQUEST['language'] : 'sql');
862
863
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', '');
864
865
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', '');
866
867
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', '');
868
869
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->defaultprops);
870
871
        $_POST['formSetOf'] = $this->getPostParam('formSetOf', '');
872
873
        $_POST['formArray'] = $this->getPostParam('formArray', '');
874
875
        $_POST['formCost'] = $this->getPostParam('formCost', '');
876
877
        $_POST['formRows'] = $this->getPostParam('formRows', '');
878
879
        $_POST['formComment'] = $this->getPostParam('formComment', '');
880
881
        $types  = $data->getTypes(true, true, true);
882
        $langs  = $data->getLanguages(true);
883
        $fnlang = strtolower($_POST['formLanguage']);
884
885
        switch ($fnlang) {
886
            case 'c':
887
                $this->printTitle($this->lang['strcreatecfunction'], 'pg.function.create.c');
888
889
                break;
890
            case 'internal':
891
                $this->printTitle($this->lang['strcreateinternalfunction'], 'pg.function.create.internal');
892
893
                break;
894
            default:
895
                $this->printTitle($this->lang['strcreateplfunction'], 'pg.function.create.pl');
896
897
                break;
898
        }
899
        $this->printMsg($msg);
900
901
        // Create string for return type list
902
        $szTypes = '';
903
        while (!$types->EOF) {
904
            $szSelected = '';
905
            if ($types->fields['typname'] == $_POST['formReturns']) {
906
                $szSelected = ' selected="selected"';
907
            }
908
            // this variable is include in the JS code bellow, so we need to ENT_QUOTES
909
            $szTypes .= '<option value="'.htmlspecialchars($types->fields['typname'], ENT_QUOTES)."\"{$szSelected}>";
910
            $szTypes .= htmlspecialchars($types->fields['typname'], ENT_QUOTES).'</option>';
911
            $types->moveNext();
912
        }
913
914
        $szFunctionName = "<td class=\"data1\"><input name=\"formFunction\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"".
915
        htmlspecialchars($_POST['formFunction']).'" /></td>';
916
917
        $szArguments = '<td class="data1"><input name="formArguments" style="width:100%;" size="16" value="'.
918
        htmlspecialchars($_POST['formArguments']).'" /></td>';
919
920
        $szSetOfSelected    = '';
921
        $szNotSetOfSelected = '';
922
        if ('' == $_POST['formSetOf']) {
923
            $szNotSetOfSelected = ' selected="selected"';
924
        } elseif ('SETOF' == $_POST['formSetOf']) {
925
            $szSetOfSelected = ' selected="selected"';
926
        }
927
        $szReturns = '<td class="data1" colspan="2">';
928
        $szReturns .= '<select name="formSetOf">';
929
        $szReturns .= "<option value=\"\"{$szNotSetOfSelected}></option>";
930
        $szReturns .= "<option value=\"SETOF\"{$szSetOfSelected}>SETOF</option>";
931
        $szReturns .= '</select>';
932
933
        $szReturns .= '<select class="select2" name="formReturns">'.$szTypes.'</select>';
934
935
        // Create string array type selector
936
937
        $szArraySelected    = '';
938
        $szNotArraySelected = '';
939
        if ('' == $_POST['formArray']) {
940
            $szNotArraySelected = ' selected="selected"';
941
        } elseif ('[]' == $_POST['formArray']) {
942
            $szArraySelected = ' selected="selected"';
943
        }
944
945
        $szReturns .= '<select name="formArray">';
946
        $szReturns .= "<option value=\"\"{$szNotArraySelected}></option>";
947
        $szReturns .= "<option value=\"[]\"{$szArraySelected}>[ ]</option>";
948
        $szReturns .= "</select>\n</td>";
949
950
        // Create string for language
951
        $szLanguage = '<td class="data1">';
952
        if ('c' == $fnlang || 'internal' == $fnlang) {
953
            $szLanguage .= $_POST['formLanguage'].PHP_EOL;
954
            $szLanguage .= "<input type=\"hidden\" name=\"formLanguage\" value=\"{$_POST['formLanguage']}\" />".PHP_EOL;
955
        } else {
956
            $szLanguage .= '<select name="formLanguage">'.PHP_EOL;
957
            while (!$langs->EOF) {
958
                $szSelected = '';
959
                if ($langs->fields['lanname'] == $_POST['formLanguage']) {
960
                    $szSelected = ' selected="selected"';
961
                }
962
                if ('c' != strtolower($langs->fields['lanname']) && 'internal' != strtolower($langs->fields['lanname'])) {
963
                    $szLanguage .= '<option value="'.htmlspecialchars($langs->fields['lanname'])."\"{$szSelected}>\n".
964
                    $this->misc->printVal($langs->fields['lanname']).'</option>';
965
                }
966
967
                $langs->moveNext();
968
            }
969
            $szLanguage .= '</select>'.PHP_EOL;
970
        }
971
972
        $szLanguage .= '</td>';
973
        $szJSArguments = "<tr><th class=\"data\" colspan=\"7\">{$this->lang['strarguments']}</th></tr>";
974
        $arrayModes    = ['IN', 'OUT', 'INOUT'];
975
        $szModes       = '<select name="formArgModes[]" style="width:100%;">';
976
        foreach ($arrayModes as $pV) {
977
            $szModes .= "<option value=\"{$pV}\">{$pV}</option>";
978
        }
979
        $szModes .= '</select>';
980
        $szArgReturns = '<select name="formArgArray[]">';
981
        $szArgReturns .= '<option value=""></option>';
982
        $szArgReturns .= '<option value="[]">[]</option>';
983
        $szArgReturns .= '</select>';
984
        $subfolder = \SUBFOLDER;
985
        if (!empty($this->conf['theme'])) {
986
            $szImgPath = \SUBFOLDER."/assets/images/themes/{$this->conf['theme']}";
987
        } else {
988
            $szImgPath = \SUBFOLDER.'/assets/images/themes/default';
989
        }
990
        if (empty($msg)) {
991
            // $this->prtrace($subfolder);
992
            $szJSTRArg = "<script type=\"text/javascript\" >addArg('{$subfolder}');</script>".PHP_EOL;
993
        } else {
994
            $szJSTRArg = '';
995
        }
996
        $szJSAddTR = "<tr id=\"parent_add_tr\" onclick=\"addArg('{$subfolder}');\" onmouseover=\"this.style.cursor='pointer'\">".PHP_EOL;
997
        $szJSAddTR .= '<td style="text-align: right" colspan="6" class="data3"><table><tr><td class="data3">';
998
        $szJSAddTR .= "<img src=\"{$szImgPath}/AddArguments.png\" alt=\"Add Argument\" /></td>";
999
        $szJSAddTR .= "<td class=\"data3\"><span style=\"font-size: 8pt\">{$this->lang['strargadd']}</span></td></tr></table></td>\n</tr>".PHP_EOL;
1000
1001
        echo '<script src="'.\SUBFOLDER."/assets/js/functions.js\" type=\"text/javascript\"></script>
1002
		<script type=\"text/javascript\">
1003
			//<![CDATA[
1004
			var g_types_select = '<select class=\"select2\" name=\"formArgType[]\">{$szTypes}</select>{$szArgReturns}';
1005
			var g_modes_select = '{$szModes}';
1006
			var g_name = '';
1007
			var g_lang_strargremove = '", htmlspecialchars($this->lang['strargremove'], ENT_QUOTES), "';
1008
			var g_lang_strargnoargs = '", htmlspecialchars($this->lang['strargnoargs'], ENT_QUOTES), "';
1009
			var g_lang_strargenableargs = '", htmlspecialchars($this->lang['strargenableargs'], ENT_QUOTES), "';
1010
			var g_lang_strargnorowabove = '", htmlspecialchars($this->lang['strargnorowabove'], ENT_QUOTES), "';
1011
			var g_lang_strargnorowbelow = '", htmlspecialchars($this->lang['strargnorowbelow'], ENT_QUOTES), "';
1012
			var g_lang_strargremoveconfirm = '", htmlspecialchars($this->lang['strargremoveconfirm'], ENT_QUOTES), "';
1013
			var g_lang_strargraise = '", htmlspecialchars($this->lang['strargraise'], ENT_QUOTES), "';
1014
			var g_lang_strarglower = '", htmlspecialchars($this->lang['strarglower'], ENT_QUOTES), "';
1015
			//]]>
1016
		</script>
1017
		";
1018
        echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
1019
        echo '<table><tbody id="args_table">'.PHP_EOL;
1020
        echo "<tr><th class=\"data required\">{$this->lang['strname']}</th>".PHP_EOL;
1021
        echo "<th class=\"data required\" colspan=\"2\">{$this->lang['strreturns']}</th>".PHP_EOL;
1022
        echo "<th class=\"data required\">{$this->lang['strproglanguage']}</th></tr>".PHP_EOL;
1023
        echo '<tr>'.PHP_EOL;
1024
        echo "{$szFunctionName}\n";
1025
        echo "{$szReturns}\n";
1026
        echo "{$szLanguage}\n";
1027
        echo '</tr>'.PHP_EOL;
1028
        echo "{$szJSArguments}\n";
1029
        echo '<tr>'.PHP_EOL;
1030
        echo "<th class=\"data required\">{$this->lang['strargmode']}</th>".PHP_EOL;
1031
        echo "<th class=\"data required\">{$this->lang['strname']}</th>".PHP_EOL;
1032
        echo "<th class=\"data required\" colspan=\"2\">{$this->lang['strargtype']}</th>".PHP_EOL;
1033
        echo '</tr>'.PHP_EOL;
1034
        echo "{$szJSAddTR}\n";
1035
1036
        if ('c' == $fnlang) {
1037
            echo "<tr><th class=\"data required\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
1038
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
1039
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
1040
            htmlspecialchars($_POST['formObjectFile']), '" /></td>'.PHP_EOL;
1041
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1042
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
1043
        } elseif ('internal' == $fnlang) {
1044
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
1045
            echo '<tr><td class="data1" colspan="4"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1046
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
1047
        } else {
1048
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strdefinition']}</th></tr>".PHP_EOL;
1049
            echo '<tr><td class="data1" colspan="4">';
1050
            echo '<textarea style="width:100%;" rows="20" cols="50" name="formDefinition">';
1051
            echo htmlspecialchars($_POST['formDefinition']);
1052
            echo '</textarea></td></tr>'.PHP_EOL;
1053
        }
1054
1055
        // Display function comment
1056
        echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strcomment']}</th></tr>".PHP_EOL;
1057
        echo '<tr><td class="data1" colspan="4"><textarea style="width:100%;" name="formComment" rows="3" cols="50">',
1058
        htmlspecialchars($_POST['formComment']), '</textarea></td></tr>'.PHP_EOL;
1059
1060
        // Display function cost options
1061
        if ($data->hasFunctionCosting()) {
1062
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
1063
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
1064
            htmlspecialchars($_POST['formCost']).'" /></td>';
1065
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"".
1066
            htmlspecialchars($_POST['formRows']).'" /></td>';
1067
        }
1068
1069
        // Display function properties
1070
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
1071
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
1072
            echo '<tr><td class="data1" colspan="4">'.PHP_EOL;
1073
            $i = 0;
1074
            foreach ($data->funcprops as $k => $v) {
1075
                echo "<select name=\"formProperties[{$i}]\">".PHP_EOL;
1076
                foreach ($v as $p) {
1077
                    echo '<option value="', htmlspecialchars($p), '"',
1078
                    ($_POST['formProperties'][$i] == $p) ? ' selected="selected"' : '',
1079
                    '>', $this->misc->printVal($p), '</option>'.PHP_EOL;
1080
                }
1081
                echo '</select><br />'.PHP_EOL;
1082
                ++$i;
1083
            }
1084
            echo '</td></tr>'.PHP_EOL;
1085
        }
1086
        echo '</tbody></table>'.PHP_EOL;
1087
        echo $szJSTRArg;
1088
        echo '<p><input type="hidden" name="action" value="save_create" />'.PHP_EOL;
1089
        echo $this->misc->form;
1090
        echo "<input type=\"submit\" value=\"{$this->lang['strcreate']}\" />".PHP_EOL;
1091
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
1092
        echo '</form>'.PHP_EOL;
1093
        echo $szJS;
1094
    }
1095
1096
    /**
1097
     * Actually creates the new function in the database.
1098
     */
1099
    public function doSaveCreate()
1100
    {
1101
        $data = $this->misc->getDatabaseAccessor();
1102
1103
        $fnlang = strtolower($_POST['formLanguage']);
1104
1105
        if ('c' == $fnlang) {
1106
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
1107
        } elseif ('internal' == $fnlang) {
1108
            $def = $_POST['formLinkSymbol'];
1109
        } else {
1110
            $def = $_POST['formDefinition'];
1111
        }
1112
1113
        $szJS = '';
1114
1115
        echo '<script src="'.\SUBFOLDER.'/assets/js/functions.js" type="text/javascript"></script>';
1116
        echo '<script type="text/javascript">'.$this->_buildJSData().'</script>';
1117
        if (!empty($_POST['formArgName'])) {
1118
            $szJS = $this->_buildJSRows($this->_buildFunctionArguments($_POST));
1119
        } else {
1120
            $subfolder = \SUBFOLDER;
1121
            // $this->prtrace($subfolder);
1122
            $szJS = '<script type="text/javascript" src="'.\SUBFOLDER.'/assets/js/functions.js">noArgsRebuild(addArg("'.$subfolder.'"));</script>';
1123
        }
1124
1125
        $cost = (isset($_POST['formCost'])) ? $_POST['formCost'] : null;
1126
        if ('' == $cost || !is_numeric($cost) || $cost != (int) $cost || $cost < 0) {
1127
            $cost = null;
1128
        }
1129
1130
        $rows = (isset($_POST['formRows'])) ? $_POST['formRows'] : null;
1131
        if ('' == $rows || !is_numeric($rows) || $rows != (int) $rows) {
1132
            $rows = null;
1133
        }
1134
1135
        // Check that they've given a name and a definition
1136
        if ('' == $_POST['formFunction']) {
1137
            $this->doCreate($this->lang['strfunctionneedsname'], $szJS);
1138
        } elseif ('internal' != $fnlang && !$def) {
1139
            $this->doCreate($this->lang['strfunctionneedsdef'], $szJS);
1140
        } else {
1141
            // Append array symbol to type if chosen
1142
            $status = $data->createFunction(
1143
                $_POST['formFunction'],
1144
                empty($_POST['nojs']) ? $this->_buildFunctionArguments($_POST) : $_POST['formArguments'],
1145
                $_POST['formReturns'].$_POST['formArray'],
1146
                $def,
1147
                $_POST['formLanguage'],
1148
                $_POST['formProperties'],
1149
                'SETOF' == $_POST['formSetOf'],
1150
                $cost,
1151
                $rows,
1152
                $_POST['formComment'],
1153
                false
1154
            );
1155
            if (0 == $status) {
1156
                $this->doDefault($this->lang['strfunctioncreated']);
1157
            } else {
1158
                $this->doCreate($this->lang['strfunctioncreatedbad'], $szJS);
1159
            }
1160
        }
1161
    }
1162
1163
    /**
1164
     * Build out the function arguments string.
1165
     *
1166
     * @param array $arrayVars
1167
     *
1168
     * @return string the imploded array vars
1169
     */
1170
    private function _buildFunctionArguments($arrayVars)
1171
    {
1172
        if (isset($_POST['formArgName'])) {
1173
            $arrayArgs = [];
1174
            foreach ($arrayVars['formArgName'] as $pK => $pV) {
1175
                $arrayArgs[] = $arrayVars['formArgModes'][$pK].' '.trim($pV).' '.trim($arrayVars['formArgType'][$pK]).$arrayVars['formArgArray'][$pK];
1176
            }
1177
1178
            return implode(',', $arrayArgs);
1179
        }
1180
1181
        return '';
1182
    }
1183
1184
    /**
1185
     * Build out JS to re-create table rows for arguments.
1186
     *
1187
     * @param string $szArgs args to parse
1188
     */
1189
    private function _buildJSRows($szArgs)
1190
    {
1191
        $arrayModes      = ['IN', 'OUT', 'INOUT'];
1192
        $arrayArgs       = explode(',', $szArgs);
1193
        $arrayProperArgs = [];
1194
        $nC              = 0;
1195
        $szReturn        = '';
1196
        $szMode          = [];
1197
        foreach ($arrayArgs as $pV) {
1198
            $arrayWords = explode(' ', $pV);
1199
            if (true === in_array($arrayWords[0], $arrayModes, true)) {
1200
                $szMode = $arrayWords[0];
1201
                array_shift($arrayWords);
1202
            }
1203
            $szArgName = array_shift($arrayWords);
1204
            if (false === strpos($arrayWords[count($arrayWords) - 1], '[]')) {
1205
                $szArgType   = implode(' ', $arrayWords);
1206
                $bArgIsArray = 'false';
1207
            } else {
1208
                $szArgType   = str_replace('[]', '', implode(' ', $arrayWords));
1209
                $bArgIsArray = 'true';
1210
            }
1211
            $arrayProperArgs[] = [$szMode, $szArgName, $szArgType, $bArgIsArray];
1212
            $subfolder         = \SUBFOLDER;
1213
            // $this->prtrace($subfolder);
1214
            $szReturn .= '<script type="text/javascript">';
1215
            $szReturn .= "RebuildArgTR('{$szMode}','{$szArgName}','{$szArgType}',new Boolean({$bArgIsArray},{$subfolder}));";
1216
            $szReturn .= '</script>;';
1217
            ++$nC;
1218
        }
1219
1220
        return $szReturn;
1221
    }
1222
1223
    private function _buildJSData()
1224
    {
1225
        $data = $this->misc->getDatabaseAccessor();
1226
1227
        $arrayModes  = ['IN', 'OUT', 'INOUT'];
1228
        $arrayTypes  = $data->getTypes(true, true, true);
1229
        $arrayPTypes = [];
1230
        $arrayPModes = [];
1231
1232
        while (!$arrayTypes->EOF) {
1233
            $arrayPTypes[] = "'".$arrayTypes->fields['typname']."'";
1234
            $arrayTypes->moveNext();
1235
        }
1236
1237
        foreach ($arrayModes as $pV) {
1238
            $arrayPModes[] = "'{$pV}'";
1239
        }
1240
1241
        $szTypes = 'g_main_types = new Array('.implode(',', $arrayPTypes).');';
1242
        $szModes = 'g_main_modes = new Array('.implode(',', $arrayPModes).');';
1243
1244
        return $szTypes.$szModes;
1245
    }
1246
1247
    /**
1248
     * Get the concatenated arguments for a function.
1249
     *
1250
     * @param \PHPPgAdmin\ADORecordSet $funcdata The funcdata record
1251
     *
1252
     * @return string The arguments of the function
1253
     */
1254
    private function _getPropertiesArgs($funcdata)
1255
    {
1256
        $data = $this->misc->getDatabaseAccessor();
1257
1258
        if ($data->hasNamedParams()) {
1259
            if (isset($funcdata->fields['proallarguments'])) {
1260
                $args_arr = $data->phpArray($funcdata->fields['proallarguments']);
1261
            } else {
1262
                $args_arr = explode(', ', $funcdata->fields['proarguments']);
1263
            }
1264
            $names_arr     = $data->phpArray($funcdata->fields['proargnames']);
1265
            $modes_arr     = $data->phpArray($funcdata->fields['proargmodes']);
1266
            $args          = '';
1267
            $args_arr_size = sizeof($args_arr);
1268
            for ($i = 0; $i < $args_arr_size; ++$i) {
1269
                if (0 != $i) {
1270
                    $args .= ', ';
1271
                }
1272
1273
                if (isset($modes_arr[$i])) {
1274
                    switch ($modes_arr[$i]) {
1275
                        case 'i':
1276
                            $args .= ' IN ';
1277
1278
                            break;
1279
                        case 'o':
1280
                            $args .= ' OUT ';
1281
1282
                            break;
1283
                        case 'b':
1284
                            $args .= ' INOUT ';
1285
1286
                            break;
1287
                        case 'v':
1288
                            $args .= ' VARIADIC ';
1289
1290
                            break;
1291
                        case 't':
1292
                            $args .= ' TABLE ';
1293
1294
                            break;
1295
                    }
1296
                }
1297
                if (isset($names_arr[$i]) && '' != $names_arr[$i]) {
1298
                    $data->fieldClean($names_arr[$i]);
1299
                    $args .= '"'.$names_arr[$i].'" ';
1300
                }
1301
                $args .= $args_arr[$i];
1302
            }
1303
        } else {
1304
            $args = $funcdata->fields['proarguments'];
1305
        }
1306
1307
        return $args;
1308
    }
1309
}
1310