Passed
Push — develop ( c2019a...2cab77 )
by Felipe
04:50
created

FunctionsController   F

Complexity

Total Complexity 151

Size/Duplication

Total Lines 1223
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 151
dl 0
loc 1223
rs 0.6314
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
B doTree() 0 26 1
C doSaveEdit() 0 47 9
B _printNavLinks() 0 102 3
C render() 0 65 12
B doDefault() 0 88 1
C _getNamedParamsArgs() 0 48 12
F doEdit() 0 179 23
C doDrop() 0 66 12
B _buildJSRows() 0 32 4
D doSaveCreate() 0 60 18
C doProperties() 0 82 10
A _buildJSData() 0 22 3
A _buildFunctionArguments() 0 12 3
F doCreate() 0 244 27
C _getPropertiesArgs() 0 54 13

How to fix   Complexity   

Complex Class

Complex classes like FunctionsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FunctionsController, and based on these observations, apply Extract Interface, too.

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 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
            default:
79
                $this->doDefault();
80
81
                break;
82
        }
83
        $output = ob_get_clean();
84
85
        $this->printHeader($this->headerTitle(), null, true, $header_template);
86
        $this->printBody();
87
        echo $output;
88
        $this->printFooter(true, $footer_template);
89
    }
90
91
    /**
92
     * Show default list of functions in the database.
93
     *
94
     * @param mixed $msg
95
     */
96
    public function doDefault($msg = '')
97
    {
98
        $data = $this->misc->getDatabaseAccessor();
99
100
        $this->printTrail('schema');
101
        $this->printTabs('schema', 'functions');
102
        $this->printMsg($msg);
103
104
        $funcs = $data->getFunctions();
105
106
        $columns = [
107
            'function'     => [
108
                'title' => $this->lang['strfunction'],
109
                'field' => Decorator::field('proproto'),
110
                'url'   => \SUBFOLDER."/redirect/function?action=properties&amp;{$this->misc->href}&amp;",
111
                'vars'  => ['function' => 'proproto', 'function_oid' => 'prooid'],
112
            ],
113
            'returns'      => [
114
                'title' => $this->lang['strreturns'],
115
                'field' => Decorator::field('proreturns'),
116
            ],
117
            'owner'        => [
118
                'title' => $this->lang['strowner'],
119
                'field' => Decorator::field('proowner'),
120
            ],
121
            'proglanguage' => [
122
                'title' => $this->lang['strproglanguage'],
123
                'field' => Decorator::field('prolanguage'),
124
            ],
125
            'actions'      => [
126
                'title' => $this->lang['stractions'],
127
            ],
128
            'comment'      => [
129
                'title' => $this->lang['strcomment'],
130
                'field' => Decorator::field('procomment'),
131
            ],
132
        ];
133
134
        $actions = [
135
            'multiactions' => [
136
                'keycols' => ['function' => 'proproto', 'function_oid' => 'prooid'],
137
                'url'     => 'functions',
138
            ],
139
            'alter'        => [
140
                'content' => $this->lang['stralter'],
141
                'attr'    => [
142
                    'href' => [
143
                        'url'     => 'functions',
144
                        'urlvars' => [
145
                            'action'       => 'edit',
146
                            'function'     => Decorator::field('proproto'),
147
                            'function_oid' => Decorator::field('prooid'),
148
                        ],
149
                    ],
150
                ],
151
            ],
152
            'drop'         => [
153
                'multiaction' => 'confirm_drop',
154
                'content'     => $this->lang['strdrop'],
155
                'attr'        => [
156
                    'href' => [
157
                        'url'     => 'functions',
158
                        'urlvars' => [
159
                            'action'       => 'confirm_drop',
160
                            'function'     => Decorator::field('proproto'),
161
                            'function_oid' => Decorator::field('prooid'),
162
                        ],
163
                    ],
164
                ],
165
            ],
166
            'privileges'   => [
167
                'content' => $this->lang['strprivileges'],
168
                'attr'    => [
169
                    'href' => [
170
                        'url'     => 'privileges',
171
                        'urlvars' => [
172
                            'subject'      => 'function',
173
                            'function'     => Decorator::field('proproto'),
174
                            'function_oid' => Decorator::field('prooid'),
175
                        ],
176
                    ],
177
                ],
178
            ],
179
        ];
180
181
        echo $this->printTable($funcs, $columns, $actions, $this->table_place, $this->lang['strnofunctions']);
182
183
        $this->_printNavLinks('functions-functions');
184
    }
185
186
    private function _printNavLinks($place, $func_full = '')
187
    {
188
        if ($place === 'functions-properties') {
189
            $navlinks = [
190
                'showall' => [
191
                    'attr'    => [
192
                        'href' => [
193
                            'url'     => 'functions',
194
                            'urlvars' => [
195
                                'server'   => $_REQUEST['server'],
196
                                'database' => $_REQUEST['database'],
197
                                'schema'   => $_REQUEST['schema'],
198
                            ],
199
                        ],
200
                    ],
201
                    'content' => $this->lang['strshowallfunctions'],
202
                ],
203
                'alter'   => [
204
                    'attr'    => [
205
                        'href' => [
206
                            'url'     => 'functions',
207
                            'urlvars' => [
208
                                'action'       => 'edit',
209
                                'server'       => $_REQUEST['server'],
210
                                'database'     => $_REQUEST['database'],
211
                                'schema'       => $_REQUEST['schema'],
212
                                'function'     => $_REQUEST['function'],
213
                                'function_oid' => $_REQUEST['function_oid'],
214
                            ],
215
                        ],
216
                    ],
217
                    'content' => $this->lang['stralter'],
218
                ],
219
                'drop'    => [
220
                    'attr'    => [
221
                        'href' => [
222
                            'url'     => 'functions',
223
                            'urlvars' => [
224
                                'action'       => 'confirm_drop',
225
                                'server'       => $_REQUEST['server'],
226
                                'database'     => $_REQUEST['database'],
227
                                'schema'       => $_REQUEST['schema'],
228
                                'function'     => $func_full,
229
                                'function_oid' => $_REQUEST['function_oid'],
230
                            ],
231
                        ],
232
                    ],
233
                    'content' => $this->lang['strdrop'],
234
                ],
235
            ];
236
        } elseif ($place === 'functions-functions') {
237
            $navlinks = [
238
                'createpl'       => [
239
                    'attr'    => [
240
                        'href' => [
241
                            'url'     => 'functions',
242
                            'urlvars' => [
243
                                'action'   => 'create',
244
                                'server'   => $_REQUEST['server'],
245
                                'database' => $_REQUEST['database'],
246
                                'schema'   => $_REQUEST['schema'],
247
                            ],
248
                        ],
249
                    ],
250
                    'content' => $this->lang['strcreateplfunction'],
251
                ],
252
                'createinternal' => [
253
                    'attr'    => [
254
                        'href' => [
255
                            'url'     => 'functions',
256
                            'urlvars' => [
257
                                'action'   => 'create',
258
                                'language' => 'internal',
259
                                'server'   => $_REQUEST['server'],
260
                                'database' => $_REQUEST['database'],
261
                                'schema'   => $_REQUEST['schema'],
262
                            ],
263
                        ],
264
                    ],
265
                    'content' => $this->lang['strcreateinternalfunction'],
266
                ],
267
                'createc'        => [
268
                    'attr'    => [
269
                        'href' => [
270
                            'url'     => 'functions',
271
                            'urlvars' => [
272
                                'action'   => 'create',
273
                                'language' => 'C',
274
                                'server'   => $_REQUEST['server'],
275
                                'database' => $_REQUEST['database'],
276
                                'schema'   => $_REQUEST['schema'],
277
                            ],
278
                        ],
279
                    ],
280
                    'content' => $this->lang['strcreatecfunction'],
281
                ],
282
            ];
283
        } else {
284
            return;
285
        }
286
287
        $this->printNavLinks($navlinks, $place, get_defined_vars());
288
    }
289
290
    /**
291
     * Generate XML for the browser tree.
292
     */
293
    public function doTree()
294
    {
295
        $data = $this->misc->getDatabaseAccessor();
296
297
        $funcs = $data->getFunctions();
298
299
        $proto = Decorator::concat(Decorator::field('proname'), ' (', Decorator::field('proarguments'), ')');
300
301
        $reqvars = $this->misc->getRequestVars('function');
302
303
        $attrs = [
304
            'text'    => $proto,
305
            'icon'    => 'Function',
306
            'toolTip' => Decorator::field('procomment'),
307
            'action'  => Decorator::redirecturl(
308
                'redirect',
309
                $reqvars,
310
                [
311
                    'action'       => 'properties',
312
                    'function'     => $proto,
313
                    'function_oid' => Decorator::field('prooid'),
314
                ]
315
            ),
316
        ];
317
318
        return $this->printTree($funcs, $attrs, 'functions');
319
    }
320
321
    /**
322
     * Function to save after editing a function.
323
     */
324
    public function doSaveEdit()
325
    {
326
        $data = $this->misc->getDatabaseAccessor();
327
328
        $fnlang = strtolower($_POST['original_lang']);
329
330
        if ('c' == $fnlang) {
331
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
332
        } elseif ('internal' == $fnlang) {
333
            $def = $_POST['formLinkSymbol'];
334
        } else {
335
            $def = $_POST['formDefinition'];
336
        }
337
        if (!$data->hasFunctionAlterSchema()) {
338
            $_POST['formFuncSchema'] = '';
339
        }
340
341
        $status = $data->setFunction(
342
            $_POST['original_function'],
343
            $_POST['formFunction'],
344
            $_POST['original_arguments'],
345
            $_POST['original_returns'],
346
            $def,
347
            $_POST['original_lang'],
348
            $_POST['formProperties'],
349
            isset($_POST['original_setof']),
350
            $_POST['original_owner'],
351
            $_POST['formFuncOwn'],
352
            $_POST['original_schema'],
353
            $_POST['formFuncSchema'],
354
            isset($_POST['formCost']) ? $_POST['formCost'] : null,
355
            isset($_POST['formRows']) ? $_POST['formRows'] : 0,
356
            $_POST['formComment']
357
        );
358
359
        if (0 == $status) {
360
            // If function has had schema altered, need to change to the new schema
361
            // and reload the browser frame.
362
            if (!empty($_POST['formFuncSchema']) && ($_POST['formFuncSchema'] != $_POST['original_schema'])) {
363
                // Jump them to the new function schema
364
                $this->misc->setCurrentSchema($_POST['formFuncSchema']);
365
                // Force a browser reload
366
                $this->misc->setReloadBrowser(true);
367
            }
368
            $this->doProperties($this->lang['strfunctionupdated']);
369
        } else {
370
            $this->doEdit($this->lang['strfunctionupdatedbad']);
371
        }
372
    }
373
374
    private function _getNamedParamsArgs($data, $fndata)
375
    {
376
        if (isset($fndata->fields['proallarguments'])) {
377
            $args_arr = $data->phpArray($fndata->fields['proallarguments']);
378
        } else {
379
            $args_arr = explode(', ', $fndata->fields['proarguments']);
380
        }
381
        $names_arr     = $data->phpArray($fndata->fields['proargnames']);
382
        $modes_arr     = $data->phpArray($fndata->fields['proargmodes']);
383
        $args          = '';
384
        $args_arr_size = sizeof($args_arr);
385
        for ($i = 0; $i < $args_arr_size; ++$i) {
386
            if (0 != $i) {
387
                $args .= ', ';
388
            }
389
390
            if (isset($modes_arr[$i])) {
391
                switch ($modes_arr[$i]) {
392
                    case 'i':
393
                        $args .= ' IN ';
394
395
                        break;
396
                    case 'o':
397
                        $args .= ' OUT ';
398
399
                        break;
400
                    case 'b':
401
                        $args .= ' INOUT ';
402
403
                        break;
404
                    case 'v':
405
                        $args .= ' VARIADIC ';
406
407
                        break;
408
                    case 't':
409
                        $args .= ' TABLE ';
410
411
                        break;
412
                }
413
            }
414
            if (isset($names_arr[$i]) && '' != $names_arr[$i]) {
415
                $data->fieldClean($names_arr[$i]);
416
                $args .= '"'.$names_arr[$i].'" ';
417
            }
418
            $args .= $args_arr[$i];
419
        }
420
421
        return $args;
422
    }
423
424
    /**
425
     * Function to allow editing of a Function.
426
     *
427
     * @param mixed $msg
428
     */
429
    public function doEdit($msg = '')
430
    {
431
        $data = $this->misc->getDatabaseAccessor();
432
433
        $this->printTrail('function');
434
        $this->printTitle($this->lang['stralter'], 'pg.function.alter');
435
        $this->printMsg($msg);
436
437
        $fndata = $data->getFunction($_REQUEST['function_oid']);
438
439
        if ($fndata->recordCount() <= 0) {
440
            echo "<p>{$this->lang['strnodata']}</p>".PHP_EOL;
441
442
            return;
443
        }
444
        $fndata->fields['proretset'] = $data->phpBool($fndata->fields['proretset']);
445
446
        // Initialise variables
447
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', $fndata->fields['prosrc']);
448
449
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->getFunctionProperties($fndata->fields));
450
451
        $_POST['formFunction'] = $this->getPostParam('formFunction', $fndata->fields['proname']);
452
453
        $_POST['formComment'] = $this->getPostParam('formComment', $fndata->fields['procomment']);
454
455
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', $fndata->fields['probin']);
456
457
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', $fndata->fields['prosrc']);
458
459
        $_POST['formFuncOwn'] = $this->getPostParam('formFuncOwn', $fndata->fields['proowner']);
460
461
        $_POST['formFuncSchema'] = $this->getPostParam('formFuncSchema', $fndata->fields['proschema']);
462
463
        if ($data->hasFunctionCosting()) {
464
            $_POST['formCost'] = $this->getPostParam('formCost', $fndata->fields['procost']);
465
466
            $_POST['formRows'] = $this->getPostParam('formRows', $fndata->fields['prorows']);
467
        }
468
469
        // Deal with named parameters
470
        if ($data->hasNamedParams()) {
471
            $args = $this->_getNamedParamsArgs($data, $fndata);
472
        } else {
473
            $args = $fndata->fields['proarguments'];
474
        }
475
476
        echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
477
        echo '<table style="width: 95%">'.PHP_EOL;
478
        echo '<tr>'.PHP_EOL;
479
        echo "<th class=\"data required\">{$this->lang['strschema']}</th>".PHP_EOL;
480
        echo "<th class=\"data required\">{$this->lang['strfunction']}</th>".PHP_EOL;
481
        echo "<th class=\"data\">{$this->lang['strarguments']}</th>".PHP_EOL;
482
        echo "<th class=\"data required\">{$this->lang['strreturns']}</th>".PHP_EOL;
483
        echo "<th class=\"data required\">{$this->lang['strproglanguage']}</th>".PHP_EOL;
484
        echo '</tr>'.PHP_EOL;
485
486
        echo '<tr>'.PHP_EOL;
487
        echo '<td class="data1">';
488
        echo '<input type="hidden" name="original_schema" value="', htmlspecialchars($fndata->fields['proschema']), '" />'.PHP_EOL;
489
        if ($data->hasFunctionAlterSchema()) {
490
            $schemas = $data->getSchemas();
491
            echo '<select name="formFuncSchema">';
492
            while (!$schemas->EOF) {
493
                $schema = $schemas->fields['nspname'];
494
                echo '<option value="', htmlspecialchars($schema), '"',
495
                ($schema == $_POST['formFuncSchema']) ? ' selected="selected"' : '', '>', htmlspecialchars($schema), '</option>'.PHP_EOL;
496
                $schemas->moveNext();
497
            }
498
            echo '</select>'.PHP_EOL;
499
        } else {
500
            echo $fndata->fields['proschema'];
501
        }
502
503
        echo '</td>'.PHP_EOL;
504
        echo '<td class="data1">';
505
        echo '<input type="hidden" name="original_function" value="', htmlspecialchars($fndata->fields['proname']), '" />'.PHP_EOL;
506
        echo "<input name=\"formFunction\" style=\"width: 100%; box-sizing: border-box;\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_POST['formFunction']), '" />';
507
        echo '</td>'.PHP_EOL;
508
509
        echo '<td class="data1">', $this->misc->printVal($args), PHP_EOL;
510
        echo '<input type="hidden" name="original_arguments" value="', htmlspecialchars($args), '" />'.PHP_EOL;
511
        echo '</td>'.PHP_EOL;
512
513
        echo '<td class="data1">';
514
        if ($fndata->fields['proretset']) {
515
            echo 'setof ';
516
        }
517
518
        echo $this->misc->printVal($fndata->fields['proresult']), PHP_EOL;
519
        echo '<input type="hidden" name="original_returns" value="', htmlspecialchars($fndata->fields['proresult']), '" />'.PHP_EOL;
520
        if ($fndata->fields['proretset']) {
521
            echo '<input type="hidden" name="original_setof" value="yes" />'.PHP_EOL;
522
        }
523
524
        echo '</td>'.PHP_EOL;
525
526
        echo '<td class="data1">', $this->misc->printVal($fndata->fields['prolanguage']), PHP_EOL;
527
        echo '<input type="hidden" name="original_lang" value="', htmlspecialchars($fndata->fields['prolanguage']), '" />'.PHP_EOL;
528
        echo '</td>'.PHP_EOL;
529
        echo '</tr>'.PHP_EOL;
530
531
        $fnlang = strtolower($fndata->fields['prolanguage']);
532
        if ('c' == $fnlang) {
533
            echo "<tr><th class=\"data required\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
534
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
535
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
536
            htmlspecialchars($_POST['formObjectFile']), '" /></td>'.PHP_EOL;
537
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
538
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
539
        } elseif ('internal' == $fnlang) {
540
            echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
541
            echo '<tr><td class="data1" colspan="5"><input type="text" name="formLinkSymbol" style="width:100%" value="',
542
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
543
        } else {
544
            echo "<tr><th class=\"data required\" colspan=\"5\">{$this->lang['strdefinition']}</th></tr>".PHP_EOL;
545
            echo '<tr><td class="data1" colspan="5">';
546
            $textarea_id = ($fnlang === 'sql' || $fnlang === 'plpgsql') ? 'query' : 'formDefinition';
547
            echo '<textarea style="width:100%;" rows="20" cols="50" id="'.$textarea_id.'" name="formDefinition">';
548
            echo htmlspecialchars($_POST['formDefinition']);
549
            echo '</textarea></td></tr>'.PHP_EOL;
550
        }
551
552
        // Display function comment
553
        echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strcomment']}</th></tr>".PHP_EOL;
554
        echo '<tr><td class="data1" colspan="5">';
555
        echo '<textarea style="width:100%;" name="formComment" rows="3" cols="50">';
556
        echo htmlspecialchars($_POST['formComment']);
557
        echo '</textarea></td></tr>'.PHP_EOL;
558
559
        // Display function cost options
560
        if ($data->hasFunctionCosting()) {
561
            echo "<tr><th class=\"data required\" colspan=\"5\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
562
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
563
            htmlspecialchars($_POST['formCost']).'" /></td>';
564
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"",
565
            htmlspecialchars($_POST['formRows']), '"', (!$fndata->fields['proretset']) ? 'disabled' : '', '/></td>';
566
        }
567
568
        // Display function properties
569
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
570
            echo "<tr><th class=\"data\" colspan=\"5\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
571
            echo '<tr><td class="data1" colspan="5">'.PHP_EOL;
572
            $i = 0;
573
            foreach ($data->funcprops as $k => $v) {
574
                echo "<select name=\"formProperties[{$i}]\">".PHP_EOL;
575
                foreach ($v as $p) {
576
                    echo '<option value="', htmlspecialchars($p), '"',
577
                    ($_POST['formProperties'][$i] == $p) ? ' selected="selected"' : '',
578
                    '>', $this->misc->printVal($p), '</option>'.PHP_EOL;
579
                }
580
                echo '</select><br />'.PHP_EOL;
581
                ++$i;
582
            }
583
            echo '</td></tr>'.PHP_EOL;
584
        }
585
586
        // function owner
587
        if ($data->hasFunctionAlterOwner()) {
588
            $users = $data->getUsers();
589
            echo "<tr><td class=\"data1\" colspan=\"5\">{$this->lang['strowner']}: <select name=\"formFuncOwn\">";
590
            while (!$users->EOF) {
591
                $uname = $users->fields['usename'];
592
                echo '<option value="', htmlspecialchars($uname), '"',
593
                ($uname == $_POST['formFuncOwn']) ? ' selected="selected"' : '', '>', htmlspecialchars($uname), '</option>'.PHP_EOL;
594
                $users->moveNext();
595
            }
596
            echo '</select>'.PHP_EOL;
597
            echo '<input type="hidden" name="original_owner" value="', htmlspecialchars($fndata->fields['proowner']), '" />'.PHP_EOL;
598
            echo '</td></tr>'.PHP_EOL;
599
        }
600
        echo '</table>'.PHP_EOL;
601
        echo '<p><input type="hidden" name="action" value="save_edit" />'.PHP_EOL;
602
        echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), '" />'.PHP_EOL;
603
        echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), '" />'.PHP_EOL;
604
        echo $this->misc->form;
605
        echo "<input type=\"submit\" value=\"{$this->lang['stralter']}\" />".PHP_EOL;
606
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
607
        echo '</form>'.PHP_EOL;
608
    }
609
610
    /**
611
     * Show read only properties of a function.
612
     *
613
     * @param mixed $msg
614
     */
615
    public function doProperties($msg = '')
616
    {
617
        $data = $this->misc->getDatabaseAccessor();
618
619
        $this->printTrail('function');
620
        $this->printTitle($this->lang['strproperties'], 'pg.function');
621
        $this->printMsg($msg);
622
623
        $funcdata  = $data->getFunction($_REQUEST['function_oid']);
624
        $func_full = '';
625
        if ($funcdata->recordCount() <= 0) {
626
            echo "<p>{$this->lang['strnodata']}</p>".PHP_EOL;
627
628
            return $this->_printNavLinks('functions-properties', $func_full);
629
        }
630
        // Deal with named parameters
631
        $args = $this->_getPropertiesArgs($funcdata);
632
633
        // Show comment if any
634
        if (null !== $funcdata->fields['procomment']) {
635
            echo '<p class="comment">', $this->misc->printVal($funcdata->fields['procomment']), '</p>'.PHP_EOL;
636
        }
637
638
        $funcdata->fields['proretset'] = $data->phpBool($funcdata->fields['proretset']);
639
        $func_full                     = $funcdata->fields['proname'].'('.$funcdata->fields['proarguments'].')';
640
641
        echo '<table style="width: 95%">'.PHP_EOL;
642
643
        echo sprintf('<tr><th class="data">%s</th>%s', $this->lang['strfunction'], PHP_EOL);
644
        echo sprintf('<th class="data">%s</th>%s', $this->lang['strarguments'], PHP_EOL);
645
        echo sprintf('<th class="data">%s</th>%s', $this->lang['strreturns'], PHP_EOL);
646
        echo sprintf('<th class="data">%s</th></tr>%s', $this->lang['strproglanguage'], PHP_EOL);
647
648
        echo '<tr><td class="data1">', $this->misc->printVal($funcdata->fields['proname']), '</td>'.PHP_EOL;
649
        echo '<td class="data1">', $this->misc->printVal($args), '</td>'.PHP_EOL;
650
        echo '<td class="data1">';
651
        if ($funcdata->fields['proretset']) {
652
            echo 'setof ';
653
        }
654
655
        echo $this->misc->printVal($funcdata->fields['proresult']), '</td>'.PHP_EOL;
656
        echo '<td class="data1">', $this->misc->printVal($funcdata->fields['prolanguage']), '</td></tr>'.PHP_EOL;
657
658
        $fnlang = strtolower($funcdata->fields['prolanguage']);
659
        if ('c' == $fnlang) {
660
            echo "<tr><th class=\"data\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
661
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
662
            echo '<tr><td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['probin']), '</td>'.PHP_EOL;
663
            echo '<td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>'.PHP_EOL;
664
        } elseif ('internal' == $fnlang) {
665
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
666
            echo '<tr><td class="data1" colspan="4">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>'.PHP_EOL;
667
        } else {
668
            echo '<tr><td class="data1" colspan="4">';
669
            echo sprintf('<pre><code class="%s hljs">%s</code></pre>', $fnlang, $funcdata->fields['prosrc']);
670
            echo '</td></tr>'.PHP_EOL;
671
        }
672
673
        // Display function cost options
674
        if ($data->hasFunctionCosting()) {
675
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
676
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: ", $this->misc->printVal($funcdata->fields['procost']), ' </td>';
677
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: ", $this->misc->printVal($funcdata->fields['prorows']), ' </td>';
678
        }
679
680
        // Show flags
681
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
682
            // Fetch an array of the function properties
683
            $funcprops = $data->getFunctionProperties($funcdata->fields);
684
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
685
            echo '<tr><td class="data1" colspan="4">'.PHP_EOL;
686
            foreach ($funcprops as $v) {
687
                echo $this->misc->printVal($v), '<br />'.PHP_EOL;
688
            }
689
            echo '</td></tr>'.PHP_EOL;
690
        }
691
692
        echo "<tr><td class=\"data1\" colspan=\"5\">{$this->lang['strowner']}: ", htmlspecialchars($funcdata->fields['proowner']), PHP_EOL;
693
        echo '</td></tr>'.PHP_EOL;
694
        echo '</table>'.PHP_EOL;
695
696
        return $this->_printNavLinks('functions-properties', $func_full);
697
    }
698
699
    /**
700
     * Show confirmation of drop and perform actual drop.
701
     *
702
     * @param mixed $confirm
703
     */
704
    public function doDrop($confirm)
705
    {
706
        $data = $this->misc->getDatabaseAccessor();
707
708
        if (empty($_REQUEST['function']) && empty($_REQUEST['ma'])) {
709
            return $this->doDefault($this->lang['strspecifyfunctiontodrop']);
710
        }
711
712
        if ($confirm) {
713
            $this->printTrail('schema');
714
            $this->printTitle($this->lang['strdrop'], 'pg.function.drop');
715
716
            echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
717
718
            //If multi drop
719
            if (isset($_REQUEST['ma'])) {
720
                foreach ($_REQUEST['ma'] as $v) {
721
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
722
                    echo '<p>', sprintf($this->lang['strconfdropfunction'], $this->misc->printVal($a['function'])), '</p>'.PHP_EOL;
723
                    echo '<input type="hidden" name="function[]" value="', htmlspecialchars($a['function']), '" />'.PHP_EOL;
724
                    echo '<input type="hidden" name="function_oid[]" value="', htmlspecialchars($a['function_oid']), '" />'.PHP_EOL;
725
                }
726
            } else {
727
                echo '<p>', sprintf($this->lang['strconfdropfunction'], $this->misc->printVal($_REQUEST['function'])), '</p>'.PHP_EOL;
728
                echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), '" />'.PHP_EOL;
729
                echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), '" />'.PHP_EOL;
730
            }
731
732
            echo '<input type="hidden" name="action" value="drop" />'.PHP_EOL;
733
734
            echo $this->misc->form;
735
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /><label for=\"cascade\">{$this->lang['strcascade']}</label></p>".PHP_EOL;
736
            echo "<input type=\"submit\" name=\"drop\" value=\"{$this->lang['strdrop']}\" />".PHP_EOL;
737
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />".PHP_EOL;
738
            echo '</form>'.PHP_EOL;
739
        } else {
740
            if (is_array($_POST['function_oid'])) {
741
                $msg    = '';
742
                $status = $data->beginTransaction();
743
                if (0 == $status) {
744
                    foreach ($_POST['function_oid'] as $k => $s) {
745
                        $status = $data->dropFunction($s, isset($_POST['cascade']));
746
                        if (0 == $status) {
747
                            $msg .= sprintf('%s: %s<br />', htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $this->lang['strfunctiondropped']);
748
                        } else {
749
                            $data->endTransaction();
750
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $this->lang['strfunctiondroppedbad']));
751
752
                            return;
753
                        }
754
                    }
755
                }
756
                if (0 == $data->endTransaction()) {
757
                    // Everything went fine, back to the Default page....
758
                    $this->misc->setReloadBrowser(true);
759
                    $this->doDefault($msg);
760
                } else {
761
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
762
                }
763
            } else {
764
                $status = $data->dropFunction($_POST['function_oid'], isset($_POST['cascade']));
765
                if (0 == $status) {
766
                    $this->misc->setReloadBrowser(true);
767
                    $this->doDefault($this->lang['strfunctiondropped']);
768
                } else {
769
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
770
                }
771
            }
772
        }
773
    }
774
775
    /**
776
     * Displays a screen where they can enter a new function.
777
     *
778
     * @param string $msg  message to display
779
     * @param mixed  $szJS
780
     */
781
    public function doCreate($msg = '', $szJS = '')
782
    {
783
        $data = $this->misc->getDatabaseAccessor();
784
785
        $this->printTrail('schema');
786
        $_POST['formFunction'] = $this->getPostParam('formFunction', '');
787
788
        $_POST['formArguments'] = $this->getPostParam('formArguments', '');
789
790
        $_POST['formReturns'] = $this->getPostParam('formReturns', '');
791
792
        $this->coalesceArr($_POST, 'formLanguage', isset($_REQUEST['language']) ? $_REQUEST['language'] : 'sql');
793
794
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', '');
795
796
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', '');
797
798
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', '');
799
800
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->defaultprops);
801
802
        $_POST['formSetOf'] = $this->getPostParam('formSetOf', '');
803
804
        $_POST['formArray'] = $this->getPostParam('formArray', '');
805
806
        $_POST['formCost'] = $this->getPostParam('formCost', '');
807
808
        $_POST['formRows'] = $this->getPostParam('formRows', '');
809
810
        $_POST['formComment'] = $this->getPostParam('formComment', '');
811
812
        $types  = $data->getTypes(true, true, true);
813
        $langs  = $data->getLanguages(true);
814
        $fnlang = strtolower($_POST['formLanguage']);
815
816
        switch ($fnlang) {
817
            case 'c':
818
                $this->printTitle($this->lang['strcreatecfunction'], 'pg.function.create.c');
819
820
                break;
821
            case 'internal':
822
                $this->printTitle($this->lang['strcreateinternalfunction'], 'pg.function.create.internal');
823
824
                break;
825
            default:
826
                $this->printTitle($this->lang['strcreateplfunction'], 'pg.function.create.pl');
827
828
                break;
829
        }
830
        $this->printMsg($msg);
831
832
        // Create string for return type list
833
        $szTypes = '';
834
        while (!$types->EOF) {
835
            $szSelected = '';
836
            if ($types->fields['typname'] == $_POST['formReturns']) {
837
                $szSelected = ' selected="selected"';
838
            }
839
            // this variable is include in the JS code bellow, so we need to ENT_QUOTES
840
            $szTypes .= '<option value="'.htmlspecialchars($types->fields['typname'], ENT_QUOTES)."\"{$szSelected}>";
841
            $szTypes .= htmlspecialchars($types->fields['typname'], ENT_QUOTES).'</option>';
842
            $types->moveNext();
843
        }
844
845
        $szFunctionName = "<td class=\"data1\"><input name=\"formFunction\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"".
846
        htmlspecialchars($_POST['formFunction']).'" /></td>';
847
848
        $szArguments = '<td class="data1"><input name="formArguments" style="width:100%;" size="16" value="'.
849
        htmlspecialchars($_POST['formArguments']).'" /></td>';
850
851
        $szSetOfSelected    = '';
852
        $szNotSetOfSelected = '';
853
        if ('' == $_POST['formSetOf']) {
854
            $szNotSetOfSelected = ' selected="selected"';
855
        } elseif ('SETOF' == $_POST['formSetOf']) {
856
            $szSetOfSelected = ' selected="selected"';
857
        }
858
        $szReturns = '<td class="data1" colspan="2">';
859
        $szReturns .= '<select name="formSetOf">';
860
        $szReturns .= "<option value=\"\"{$szNotSetOfSelected}></option>";
861
        $szReturns .= "<option value=\"SETOF\"{$szSetOfSelected}>SETOF</option>";
862
        $szReturns .= '</select>';
863
864
        $szReturns .= '<select class="select2" name="formReturns">'.$szTypes.'</select>';
865
866
        // Create string array type selector
867
868
        $szArraySelected    = '';
869
        $szNotArraySelected = '';
870
        if ('' == $_POST['formArray']) {
871
            $szNotArraySelected = ' selected="selected"';
872
        } elseif ('[]' == $_POST['formArray']) {
873
            $szArraySelected = ' selected="selected"';
874
        }
875
876
        $szReturns .= '<select name="formArray">';
877
        $szReturns .= "<option value=\"\"{$szNotArraySelected}></option>";
878
        $szReturns .= "<option value=\"[]\"{$szArraySelected}>[ ]</option>";
879
        $szReturns .= "</select>\n</td>";
880
881
        // Create string for language
882
        $szLanguage = '<td class="data1">';
883
        if ('c' == $fnlang || 'internal' == $fnlang) {
884
            $szLanguage .= $_POST['formLanguage'].PHP_EOL;
885
            $szLanguage .= "<input type=\"hidden\" name=\"formLanguage\" value=\"{$_POST['formLanguage']}\" />".PHP_EOL;
886
        } else {
887
            $szLanguage .= '<select name="formLanguage">'.PHP_EOL;
888
            while (!$langs->EOF) {
889
                $szSelected = '';
890
                if ($langs->fields['lanname'] == $_POST['formLanguage']) {
891
                    $szSelected = ' selected="selected"';
892
                }
893
                if ('c' != strtolower($langs->fields['lanname']) && 'internal' != strtolower($langs->fields['lanname'])) {
894
                    $szLanguage .= '<option value="'.htmlspecialchars($langs->fields['lanname'])."\"{$szSelected}>\n".
895
                    $this->misc->printVal($langs->fields['lanname']).'</option>';
896
                }
897
898
                $langs->moveNext();
899
            }
900
            $szLanguage .= '</select>'.PHP_EOL;
901
        }
902
903
        $szLanguage .= '</td>';
904
        $szJSArguments = "<tr><th class=\"data\" colspan=\"7\">{$this->lang['strarguments']}</th></tr>";
905
        $arrayModes    = ['IN', 'OUT', 'INOUT'];
906
        $szModes       = '<select name="formArgModes[]" style="width:100%;">';
907
        foreach ($arrayModes as $pV) {
908
            $szModes .= "<option value=\"{$pV}\">{$pV}</option>";
909
        }
910
        $szModes .= '</select>';
911
        $szArgReturns = '<select name="formArgArray[]">';
912
        $szArgReturns .= '<option value=""></option>';
913
        $szArgReturns .= '<option value="[]">[]</option>';
914
        $szArgReturns .= '</select>';
915
        $subfolder = \SUBFOLDER;
916
        if (!empty($this->conf['theme'])) {
917
            $szImgPath = \SUBFOLDER."/assets/images/themes/{$this->conf['theme']}";
918
        } else {
919
            $szImgPath = \SUBFOLDER.'/assets/images/themes/default';
920
        }
921
        if (empty($msg)) {
922
            // $this->prtrace($subfolder);
923
            $szJSTRArg = "<script type=\"text/javascript\" >addArg('{$subfolder}');</script>".PHP_EOL;
924
        } else {
925
            $szJSTRArg = '';
926
        }
927
        $szJSAddTR = "<tr id=\"parent_add_tr\" onclick=\"addArg('{$subfolder}');\" onmouseover=\"this.style.cursor='pointer'\">".PHP_EOL;
928
        $szJSAddTR .= '<td style="text-align: right" colspan="6" class="data3"><table><tr><td class="data3">';
929
        $szJSAddTR .= "<img src=\"{$szImgPath}/AddArguments.png\" alt=\"Add Argument\" /></td>";
930
        $szJSAddTR .= "<td class=\"data3\"><span style=\"font-size: 8pt\">{$this->lang['strargadd']}</span></td></tr></table></td>\n</tr>".PHP_EOL;
931
932
        echo '<script src="'.\SUBFOLDER."/assets/js/functions.js\" type=\"text/javascript\"></script>
933
		<script type=\"text/javascript\">
934
			//<![CDATA[
935
			var g_types_select = '<select class=\"select2\" name=\"formArgType[]\">{$szTypes}</select>{$szArgReturns}';
936
			var g_modes_select = '{$szModes}';
937
			var g_name = '';
938
			var g_lang_strargremove = '", htmlspecialchars($this->lang['strargremove'], ENT_QUOTES), "';
939
			var g_lang_strargnoargs = '", htmlspecialchars($this->lang['strargnoargs'], ENT_QUOTES), "';
940
			var g_lang_strargenableargs = '", htmlspecialchars($this->lang['strargenableargs'], ENT_QUOTES), "';
941
			var g_lang_strargnorowabove = '", htmlspecialchars($this->lang['strargnorowabove'], ENT_QUOTES), "';
942
			var g_lang_strargnorowbelow = '", htmlspecialchars($this->lang['strargnorowbelow'], ENT_QUOTES), "';
943
			var g_lang_strargremoveconfirm = '", htmlspecialchars($this->lang['strargremoveconfirm'], ENT_QUOTES), "';
944
			var g_lang_strargraise = '", htmlspecialchars($this->lang['strargraise'], ENT_QUOTES), "';
945
			var g_lang_strarglower = '", htmlspecialchars($this->lang['strarglower'], ENT_QUOTES), "';
946
			//]]>
947
		</script>
948
		";
949
        echo '<form action="'.\SUBFOLDER.'/src/views/functions" method="post">'.PHP_EOL;
950
        echo '<table><tbody id="args_table">'.PHP_EOL;
951
        echo "<tr><th class=\"data required\">{$this->lang['strname']}</th>".PHP_EOL;
952
        echo "<th class=\"data required\" colspan=\"2\">{$this->lang['strreturns']}</th>".PHP_EOL;
953
        echo "<th class=\"data required\">{$this->lang['strproglanguage']}</th></tr>".PHP_EOL;
954
        echo '<tr>'.PHP_EOL;
955
        echo "{$szFunctionName}\n";
956
        echo "{$szReturns}\n";
957
        echo "{$szLanguage}\n";
958
        echo '</tr>'.PHP_EOL;
959
        echo "{$szJSArguments}\n";
960
        echo '<tr>'.PHP_EOL;
961
        echo "<th class=\"data required\">{$this->lang['strargmode']}</th>".PHP_EOL;
962
        echo "<th class=\"data required\">{$this->lang['strname']}</th>".PHP_EOL;
963
        echo "<th class=\"data required\" colspan=\"2\">{$this->lang['strargtype']}</th>".PHP_EOL;
964
        echo '</tr>'.PHP_EOL;
965
        echo "{$szJSAddTR}\n";
966
967
        if ('c' == $fnlang) {
968
            echo "<tr><th class=\"data required\" colspan=\"2\">{$this->lang['strobjectfile']}</th>".PHP_EOL;
969
            echo "<th class=\"data\" colspan=\"2\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
970
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
971
            htmlspecialchars($_POST['formObjectFile']), '" /></td>'.PHP_EOL;
972
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
973
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
974
        } elseif ('internal' == $fnlang) {
975
            echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strlinksymbol']}</th></tr>".PHP_EOL;
976
            echo '<tr><td class="data1" colspan="4"><input type="text" name="formLinkSymbol" style="width:100%" value="',
977
            htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>'.PHP_EOL;
978
        } else {
979
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strdefinition']}</th></tr>".PHP_EOL;
980
            echo '<tr><td class="data1" colspan="4">';
981
            echo '<textarea style="width:100%;" rows="20" cols="50" name="formDefinition">';
982
            echo htmlspecialchars($_POST['formDefinition']);
983
            echo '</textarea></td></tr>'.PHP_EOL;
984
        }
985
986
        // Display function comment
987
        echo "<tr><th class=\"data\" colspan=\"4\">{$this->lang['strcomment']}</th></tr>".PHP_EOL;
988
        echo '<tr><td class="data1" colspan="4"><textarea style="width:100%;" name="formComment" rows="3" cols="50">',
989
        htmlspecialchars($_POST['formComment']), '</textarea></td></tr>'.PHP_EOL;
990
991
        // Display function cost options
992
        if ($data->hasFunctionCosting()) {
993
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strfunctioncosting']}</th></tr>".PHP_EOL;
994
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"".
995
            htmlspecialchars($_POST['formCost']).'" /></td>';
996
            echo "<td class=\"data1\" colspan=\"2\">{$this->lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"".
997
            htmlspecialchars($_POST['formRows']).'" /></td>';
998
        }
999
1000
        // Display function properties
1001
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
1002
            echo "<tr><th class=\"data required\" colspan=\"4\">{$this->lang['strproperties']}</th></tr>".PHP_EOL;
1003
            echo '<tr><td class="data1" colspan="4">'.PHP_EOL;
1004
            $i = 0;
1005
            foreach ($data->funcprops as $k => $v) {
1006
                echo "<select name=\"formProperties[{$i}]\">".PHP_EOL;
1007
                foreach ($v as $p) {
1008
                    echo '<option value="', htmlspecialchars($p), '"',
1009
                    ($_POST['formProperties'][$i] == $p) ? ' selected="selected"' : '',
1010
                    '>', $this->misc->printVal($p), '</option>'.PHP_EOL;
1011
                }
1012
                echo '</select><br />'.PHP_EOL;
1013
                ++$i;
1014
            }
1015
            echo '</td></tr>'.PHP_EOL;
1016
        }
1017
        echo '</tbody></table>'.PHP_EOL;
1018
        echo $szJSTRArg;
1019
        echo '<p><input type="hidden" name="action" value="save_create" />'.PHP_EOL;
1020
        echo $this->misc->form;
1021
        echo "<input type=\"submit\" value=\"{$this->lang['strcreate']}\" />".PHP_EOL;
1022
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
1023
        echo '</form>'.PHP_EOL;
1024
        echo $szJS;
1025
    }
1026
1027
    /**
1028
     * Actually creates the new function in the database.
1029
     */
1030
    public function doSaveCreate()
1031
    {
1032
        $data = $this->misc->getDatabaseAccessor();
1033
1034
        $fnlang = strtolower($_POST['formLanguage']);
1035
1036
        if ('c' == $fnlang) {
1037
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
1038
        } elseif ('internal' == $fnlang) {
1039
            $def = $_POST['formLinkSymbol'];
1040
        } else {
1041
            $def = $_POST['formDefinition'];
1042
        }
1043
1044
        $szJS = '';
1045
1046
        echo '<script src="'.\SUBFOLDER.'/assets/js/functions.js" type="text/javascript"></script>';
1047
        echo '<script type="text/javascript">'.$this->_buildJSData().'</script>';
1048
        if (!empty($_POST['formArgName'])) {
1049
            $szJS = $this->_buildJSRows($this->_buildFunctionArguments($_POST));
1050
        } else {
1051
            $subfolder = \SUBFOLDER;
1052
            // $this->prtrace($subfolder);
1053
            $szJS = '<script type="text/javascript" src="'.\SUBFOLDER.'/assets/js/functions.js">noArgsRebuild(addArg("'.$subfolder.'"));</script>';
1054
        }
1055
1056
        $cost = (isset($_POST['formCost'])) ? $_POST['formCost'] : null;
1057
        if ('' == $cost || !is_numeric($cost) || $cost != (int) $cost || $cost < 0) {
1058
            $cost = null;
1059
        }
1060
1061
        $rows = (isset($_POST['formRows'])) ? $_POST['formRows'] : null;
1062
        if ('' == $rows || !is_numeric($rows) || $rows != (int) $rows) {
1063
            $rows = null;
1064
        }
1065
1066
        // Check that they've given a name and a definition
1067
        if ('' == $_POST['formFunction']) {
1068
            $this->doCreate($this->lang['strfunctionneedsname'], $szJS);
1069
        } elseif ('internal' != $fnlang && !$def) {
1070
            $this->doCreate($this->lang['strfunctionneedsdef'], $szJS);
1071
        } else {
1072
            // Append array symbol to type if chosen
1073
            $status = $data->createFunction(
1074
                $_POST['formFunction'],
1075
                empty($_POST['nojs']) ? $this->_buildFunctionArguments($_POST) : $_POST['formArguments'],
1076
                $_POST['formReturns'].$_POST['formArray'],
1077
                $def,
1078
                $_POST['formLanguage'],
1079
                $_POST['formProperties'],
1080
                'SETOF' == $_POST['formSetOf'],
1081
                $cost,
1082
                $rows,
1083
                $_POST['formComment'],
1084
                false
1085
            );
1086
            if (0 == $status) {
1087
                $this->doDefault($this->lang['strfunctioncreated']);
1088
            } else {
1089
                $this->doCreate($this->lang['strfunctioncreatedbad'], $szJS);
1090
            }
1091
        }
1092
    }
1093
1094
    /**
1095
     * Build out the function arguments string.
1096
     *
1097
     * @param array $arrayVars
1098
     *
1099
     * @return string the imploded array vars
1100
     */
1101
    private function _buildFunctionArguments($arrayVars)
1102
    {
1103
        if (isset($_POST['formArgName'])) {
1104
            $arrayArgs = [];
1105
            foreach ($arrayVars['formArgName'] as $pK => $pV) {
1106
                $arrayArgs[] = $arrayVars['formArgModes'][$pK].' '.trim($pV).' '.trim($arrayVars['formArgType'][$pK]).$arrayVars['formArgArray'][$pK];
1107
            }
1108
1109
            return implode(',', $arrayArgs);
1110
        }
1111
1112
        return '';
1113
    }
1114
1115
    /**
1116
     * Build out JS to re-create table rows for arguments.
1117
     *
1118
     * @param string $szArgs args to parse
1119
     */
1120
    private function _buildJSRows($szArgs)
1121
    {
1122
        $arrayModes      = ['IN', 'OUT', 'INOUT'];
1123
        $arrayArgs       = explode(',', $szArgs);
1124
        $arrayProperArgs = [];
1125
        $nC              = 0;
1126
        $szReturn        = '';
1127
        $szMode          = [];
1128
        foreach ($arrayArgs as $pV) {
1129
            $arrayWords = explode(' ', $pV);
1130
            if (true === in_array($arrayWords[0], $arrayModes, true)) {
1131
                $szMode = $arrayWords[0];
1132
                array_shift($arrayWords);
1133
            }
1134
            $szArgName = array_shift($arrayWords);
1135
            if (false === strpos($arrayWords[count($arrayWords) - 1], '[]')) {
1136
                $szArgType   = implode(' ', $arrayWords);
1137
                $bArgIsArray = 'false';
1138
            } else {
1139
                $szArgType   = str_replace('[]', '', implode(' ', $arrayWords));
1140
                $bArgIsArray = 'true';
1141
            }
1142
            $arrayProperArgs[] = [$szMode, $szArgName, $szArgType, $bArgIsArray];
1143
            $subfolder         = \SUBFOLDER;
1144
            // $this->prtrace($subfolder);
1145
            $szReturn .= '<script type="text/javascript">';
1146
            $szReturn .= "RebuildArgTR('{$szMode}','{$szArgName}','{$szArgType}',new Boolean({$bArgIsArray},{$subfolder}));";
1147
            $szReturn .= '</script>;';
1148
            ++$nC;
1149
        }
1150
1151
        return $szReturn;
1152
    }
1153
1154
    private function _buildJSData()
1155
    {
1156
        $data = $this->misc->getDatabaseAccessor();
1157
1158
        $arrayModes  = ['IN', 'OUT', 'INOUT'];
1159
        $arrayTypes  = $data->getTypes(true, true, true);
1160
        $arrayPTypes = [];
1161
        $arrayPModes = [];
1162
1163
        while (!$arrayTypes->EOF) {
1164
            $arrayPTypes[] = "'".$arrayTypes->fields['typname']."'";
1165
            $arrayTypes->moveNext();
1166
        }
1167
1168
        foreach ($arrayModes as $pV) {
1169
            $arrayPModes[] = "'{$pV}'";
1170
        }
1171
1172
        $szTypes = 'g_main_types = new Array('.implode(',', $arrayPTypes).');';
1173
        $szModes = 'g_main_modes = new Array('.implode(',', $arrayPModes).');';
1174
1175
        return $szTypes.$szModes;
1176
    }
1177
1178
    /**
1179
     * Get the concatenated arguments for a function.
1180
     *
1181
     * @param \PHPPgAdmin\ADORecordSet $funcdata The funcdata record
1182
     *
1183
     * @return string The arguments of the function
1184
     */
1185
    private function _getPropertiesArgs($funcdata)
1186
    {
1187
        $data = $this->misc->getDatabaseAccessor();
1188
1189
        if ($data->hasNamedParams()) {
1190
            if (isset($funcdata->fields['proallarguments'])) {
1191
                $args_arr = $data->phpArray($funcdata->fields['proallarguments']);
1192
            } else {
1193
                $args_arr = explode(', ', $funcdata->fields['proarguments']);
1194
            }
1195
            $names_arr     = $data->phpArray($funcdata->fields['proargnames']);
1196
            $modes_arr     = $data->phpArray($funcdata->fields['proargmodes']);
1197
            $args          = '';
1198
            $args_arr_size = sizeof($args_arr);
1199
            for ($i = 0; $i < $args_arr_size; ++$i) {
1200
                if (0 != $i) {
1201
                    $args .= ', ';
1202
                }
1203
1204
                if (isset($modes_arr[$i])) {
1205
                    switch ($modes_arr[$i]) {
1206
                        case 'i':
1207
                            $args .= ' IN ';
1208
1209
                            break;
1210
                        case 'o':
1211
                            $args .= ' OUT ';
1212
1213
                            break;
1214
                        case 'b':
1215
                            $args .= ' INOUT ';
1216
1217
                            break;
1218
                        case 'v':
1219
                            $args .= ' VARIADIC ';
1220
1221
                            break;
1222
                        case 't':
1223
                            $args .= ' TABLE ';
1224
1225
                            break;
1226
                    }
1227
                }
1228
                if (isset($names_arr[$i]) && '' != $names_arr[$i]) {
1229
                    $data->fieldClean($names_arr[$i]);
1230
                    $args .= '"'.$names_arr[$i].'" ';
1231
                }
1232
                $args .= $args_arr[$i];
1233
            }
1234
        } else {
1235
            $args = $funcdata->fields['proarguments'];
1236
        }
1237
1238
        return $args;
1239
    }
1240
}
1241