Test Failed
Pull Request — develop (#380)
by Felipe
04:11
created

FunctionsController::doEdit()   F

Complexity

Conditions 23
Paths 1537

Size

Total Lines 188
Code Lines 130

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 130
c 1
b 0
f 0
nc 1537
nop 1
dl 0
loc 188
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use ADORecordSet;
10
use PHPPgAdmin\Decorators\Decorator;
11
12
/**
13
 * Base controller class.
14
 */
15
class FunctionsController extends BaseController
16
{
17
    public $table_place = 'functions-functions';
18
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
34
        switch ($this->action) {
35
            case 'save_create':
36
                if (null !== $this->getPostParam('cancel')) {
37
                    $this->doDefault();
38
                } else {
39
                    $this->doSaveCreate();
40
                }
41
42
                break;
43
            case 'create':
44
                $header_template = 'header_select2.twig';
45
                $this->doCreate();
46
47
                break;
48
            case 'drop':
49
                if (null !== $this->getPostParam('drop')) {
50
                    $this->doDrop(false);
51
                } else {
52
                    $this->doDefault();
53
                }
54
55
                break;
56
            case 'confirm_drop':
57
                $this->doDrop(true);
58
59
                break;
60
            case 'save_edit':
61
                if (null !== $this->getPostParam('cancel')) {
62
                    $this->doDefault();
63
                } else {
64
                    $this->doSaveEdit();
65
                }
66
67
                break;
68
            case 'edit':
69
                $header_template = 'header_sqledit.twig';
70
                $footer_template = 'footer_sqledit.twig';
71
                $this->doEdit();
72
73
                break;
74
            case 'properties':
75
                $header_template = 'header_highlight.twig';
76
                $this->doProperties();
77
78
                break;
79
            case 'show':
80
                if (isset($_GET['function'], $_GET['function_oid'])) {
81
                    $header_template = 'header_highlight.twig';
82
                    $this->showDefinition();
83
                } else {
84
                    $this->doDefault();
85
                }
86
87
                break;
88
89
            default:
90
                $this->doDefault();
91
92
                break;
93
        }
94
        $output = \ob_get_clean();
95
96
        $this->printHeader($this->headerTitle(), null, true, $header_template);
97
        $this->printBody();
98
        echo $output;
99
        $this->printFooter(true, $footer_template);
100
    }
101
102
    /**
103
     * Show default list of functions in the database.
104
     *
105
     * @param mixed $msg
106
     */
107
    public function doDefault($msg = ''): void
108
    {
109
        $data = $this->misc->getDatabaseAccessor();
110
111
        $this->printTrail('schema');
112
        $this->printTabs('schema', 'functions');
113
        $this->printMsg($msg);
114
115
        $funcs = $data->getFunctions();
116
117
        $columns = [
118
            'function' => [
119
                'title' => $this->lang['strfunction'],
120
                'field' => Decorator::field('proproto'),
121
                'url'=>containerInstance()->getDestinationWithLastTab('function'),
122
                    '/redirect/function?action=properties&amp;%s&amp;',
123
                    $this->misc->href
124
                ),
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ')', expecting ',' or ']' on line 124 at column 16
Loading history...
125
                'vars' => ['function' => 'proproto', 'function_oid' => 'prooid'],
126
            ],
127
            'returns' => [
128
                'title' => $this->lang['strreturns'],
129
                'field' => Decorator::field('proreturns'),
130
            ],
131
            'owner' => [
132
                'title' => $this->lang['strowner'],
133
                'field' => Decorator::field('proowner'),
134
            ],
135
            'proglanguage' => [
136
                'title' => $this->lang['strproglanguage'],
137
                'field' => Decorator::field('prolanguage'),
138
            ],
139
            'actions' => [
140
                'title' => $this->lang['stractions'],
141
            ],
142
            'comment' => [
143
                'title' => $this->lang['strcomment'],
144
                'field' => Decorator::field('procomment'),
145
            ],
146
        ];
147
         $actions = [
148
            'multiactions' => [
149
                'keycols' => ['function' => 'proproto', 'function_oid' => 'prooid'],
150
                'url' => 'functions',
151
            ],
152
            'alter' => [
153
                'content' => $this->lang['stralter'],
154
                'attr' => [
155
                    'href' => [
156
                        'url' => 'functions',
157
                        'urlvars' => [
158
                            'action' => 'edit',
159
                            'function' => Decorator::field('proproto'),
160
                            'function_oid' => Decorator::field('prooid'),
161
                        ],
162
                    ],
163
                ],
164
            ],
165
            'drop' => [
166
                'multiaction' => 'confirm_drop',
167
                'content' => $this->lang['strdrop'],
168
                'attr' => [
169
                    'href' => [
170
                        'url' => 'functions',
171
                        'urlvars' => [
172
                            'action' => 'confirm_drop',
173
                            'function' => Decorator::field('proproto'),
174
                            'function_oid' => Decorator::field('prooid'),
175
                        ],
176
                    ],
177
                ],
178
            ],
179
            'privileges' => [
180
                'content' => $this->lang['strprivileges'],
181
                'attr' => [
182
                    'href' => [
183
                        'url' => 'privileges',
184
                        'urlvars' => [
185
                            'subject' => 'function',
186
                            'function' => Decorator::field('proproto'),
187
                            'function_oid' => Decorator::field('prooid'),
188
                        ],
189
                    ],
190
                ],
191
            ],
192
        ];
193
194
        echo $this->printTable($funcs, $columns, $actions, $this->table_place, $this->lang['strnofunctions']);
195
196
        $this->_printNavLinks('functions-functions');
197
    }
198
199
    /**
200
     * Generate XML for the browser tree.
201
     *
202
     * @return \Slim\Http\Response|string
203
     */
204
    public function doTree()
205
    {
206
        $data = $this->misc->getDatabaseAccessor();
207
208
        $funcs = $data->getFunctions();
209
210
        $proto = Decorator::concat(Decorator::field('proname'), ' (', Decorator::field('proarguments'), ')');
211
212
        $reqvars = $this->misc->getRequestVars('function');
213
214
        $attrs = [
215
            'text' => $proto,
216
            'icon' => 'Function',
217
            'toolTip' => Decorator::field('procomment'),
218
            'action' => Decorator::redirecturl(
219
                'redirect',
220
                $reqvars,
221
                [
222
                    'action' => 'properties',
223
                    'function' => $proto,
224
                    'function_oid' => Decorator::field('prooid'),
225
                ]
226
            ),
227
        ];
228
 
229
        return $this->printTree($funcs, $attrs, 'functions');
230
    }
231
232
    /**
233
     * Function to save after editing a function.
234
     */
235
    public function doSaveEdit(): void
236
    {
237
        $data = $this->misc->getDatabaseAccessor();
238
239
        $fnlang = \mb_strtolower($_POST['original_lang']);
240
241
        if ('c' === $fnlang) {
242
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
243
        } elseif ('internal' === $fnlang) {
244
            $def = $_POST['formLinkSymbol'];
245
        } else {
246
            $def = $_POST['formDefinition'];
247
        }
248
249
        if (!$data->hasFunctionAlterSchema()) {
250
            $_POST['formFuncSchema'] = '';
251
        }
252
253
        $status = $data->setFunction(
254
            $_POST['original_function'],
255
            $_POST['formFunction'],
256
            $_POST['original_arguments'],
257
            $_POST['original_returns'],
258
            $def,
259
            $_POST['original_lang'],
260
            $_POST['formProperties'],
261
            isset($_POST['original_setof']),
262
            $_POST['original_owner'],
263
            $_POST['formFuncOwn'],
264
            $_POST['original_schema'],
265
            $_POST['formFuncSchema'],
266
            $_POST['formCost'] ?? null,
267
            $_POST['formRows'] ?? 0,
268
            $_POST['formComment']
269
        );
270
271
        if (0 === $status) {
272
            // If function has had schema altered, need to change to the new schema
273
            // and reload the browser frame.
274
            if (!empty($_POST['formFuncSchema']) && ($_POST['formFuncSchema'] !== $_POST['original_schema'])) {
275
                // Jump them to the new function schema
276
                $this->misc->setCurrentSchema($_POST['formFuncSchema']);
277
                // Force a browser reload
278
                $this->view->setReloadBrowser(true);
279
            }
280
            $this->doProperties($this->lang['strfunctionupdated']);
281
        } else {
282
            $this->doEdit($this->lang['strfunctionupdatedbad']);
283
        }
284
    }
285
286
    /**
287
     * Function to allow editing of a Function.
288
     *
289
     * @param mixed $msg
290
     */
291
    public function doEdit($msg = ''): void
292
    {
293
        $data = $this->misc->getDatabaseAccessor();
294
295
        $this->printTrail('function');
296
        $this->printTabs('function', 'definition');
297
        $this->printTitle($this->lang['stralter'], 'pg.function.alter');
298
        $this->printMsg($msg);
299
300
        $fndata = $data->getFunction($_REQUEST['function_oid']);
301
302
        if (0 >= $fndata->RecordCount()) {
303
            echo \sprintf(
304
                '<p>%s</p>',
305
                $this->lang['strnodata']
306
            ) . \PHP_EOL;
307
308
            return;
309
        }
310
        $fndata->fields['proretset'] = $data->phpBool($fndata->fields['proretset']);
311
312
        // Initialise variables
313
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', $fndata->fields['prosrc']);
314
315
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->getFunctionProperties($fndata->fields));
316
317
        $_POST['formFunction'] = $this->getPostParam('formFunction', $fndata->fields['proname']);
318
319
        $_POST['formComment'] = $this->getPostParam('formComment', $fndata->fields['procomment']);
320
321
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', $fndata->fields['probin']);
322
323
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', $fndata->fields['prosrc']);
324
325
        $_POST['formFuncOwn'] = $this->getPostParam('formFuncOwn', $fndata->fields['proowner']);
326
327
        $_POST['formFuncSchema'] = $this->getPostParam('formFuncSchema', $fndata->fields['proschema']);
328
329
        if ($data->hasFunctionCosting()) {
330
            $_POST['formCost'] = $this->getPostParam('formCost', $fndata->fields['procost']);
331
332
            $_POST['formRows'] = $this->getPostParam('formRows', $fndata->fields['prorows']);
333
        }
334
335
        // Deal with named parameters
336
        if ($data->hasNamedParams()) {
337
            $args = $this->_getNamedParamsArgs($data, $fndata);
338
        } else {
339
            $args = $fndata->fields['proarguments'];
340
        }
341
342
        echo '<form action="' . \containerInstance()->subFolder . '/src/views/functions" method="post">' . \PHP_EOL;
343
        echo '<table style="width: 95%">' . \PHP_EOL;
344
        echo '<tr>' . \PHP_EOL;
345
        echo \sprintf(
346
            '<th class="data required">%s</th>',
347
            $this->lang['strschema']
348
        ) . \PHP_EOL;
349
        echo \sprintf(
350
            '<th class="data required">%s</th>',
351
            $this->lang['strfunction']
352
        ) . \PHP_EOL;
353
        echo \sprintf(
354
            '<th class="data">%s</th>',
355
            $this->lang['strarguments']
356
        ) . \PHP_EOL;
357
        echo \sprintf(
358
            '<th class="data required">%s</th>',
359
            $this->lang['strreturns']
360
        ) . \PHP_EOL;
361
        echo \sprintf(
362
            '<th class="data required">%s</th>',
363
            $this->lang['strproglanguage']
364
        ) . \PHP_EOL;
365
        echo '</tr>' . \PHP_EOL;
366
367
        echo '<tr>' . \PHP_EOL;
368
        echo '<td class="data1">';
369
        echo '<input type="hidden" name="original_schema" value="', \htmlspecialchars($fndata->fields['proschema']), '" />' . \PHP_EOL;
370
371
        if ($data->hasFunctionAlterSchema()) {
372
            $schemas = $data->getSchemas();
373
            echo '<select name="formFuncSchema">';
374
375
            while (!$schemas->EOF) {
376
                $schema = $schemas->fields['nspname'];
377
                echo '<option value="', \htmlspecialchars($schema), '"',
378
                ($schema === $_POST['formFuncSchema']) ? ' selected="selected"' : '', '>', \htmlspecialchars($schema), '</option>' . \PHP_EOL;
379
                $schemas->MoveNext();
380
            }
381
            echo '</select>' . \PHP_EOL;
382
        } else {
383
            echo $fndata->fields['proschema'];
384
        }
385
386
        echo '</td>' . \PHP_EOL;
387
        echo '<td class="data1">';
388
        echo '<input type="hidden" name="original_function" value="', \htmlspecialchars($fndata->fields['proname']), '" />' . \PHP_EOL;
389
        echo \sprintf(
390
            '<input name="formFunction" style="width: 100%; box-sizing: border-box;" maxlength="%s" value="',
391
            $data->_maxNameLen
392
        ), \htmlspecialchars($_POST['formFunction']), '" />';
393
        echo '</td>' . \PHP_EOL;
394
395
        echo '<td class="data1">', $this->misc->printVal($args), \PHP_EOL;
396
        echo '<input type="hidden" name="original_arguments" value="', \htmlspecialchars($args), '" />' . \PHP_EOL;
397
        echo '</td>' . \PHP_EOL;
398
399
        echo '<td class="data1">';
400
401
        if ($fndata->fields['proretset']) {
402
            echo 'setof ';
403
        }
404
405
        echo $this->misc->printVal($fndata->fields['proresult']), \PHP_EOL;
406
        echo '<input type="hidden" name="original_returns" value="', \htmlspecialchars($fndata->fields['proresult']), '" />' . \PHP_EOL;
407
408
        if ($fndata->fields['proretset']) {
409
            echo '<input type="hidden" name="original_setof" value="yes" />' . \PHP_EOL;
410
        }
411
412
        echo '</td>' . \PHP_EOL;
413
414
        echo '<td class="data1">', $this->misc->printVal($fndata->fields['prolanguage']), \PHP_EOL;
415
        echo '<input type="hidden" name="original_lang" value="', \htmlspecialchars($fndata->fields['prolanguage']), '" />' . \PHP_EOL;
416
        echo '</td>' . \PHP_EOL;
417
        echo '</tr>' . \PHP_EOL;
418
419
        $fnlang = \mb_strtolower($fndata->fields['prolanguage']);
420
421
        if ('c' === $fnlang) {
422
            echo \sprintf(
423
                '<tr><th class="data required" colspan="2">%s</th>',
424
                $this->lang['strobjectfile']
425
            ) . \PHP_EOL;
426
            echo \sprintf(
427
                '<th class="data" colspan="2">%s</th></tr>',
428
                $this->lang['strlinksymbol']
429
            ) . \PHP_EOL;
430
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
431
            \htmlspecialchars($_POST['formObjectFile']), '" /></td>' . \PHP_EOL;
432
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
433
            \htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>' . \PHP_EOL;
434
        } elseif ('internal' === $fnlang) {
435
            echo \sprintf(
436
                '<tr><th class="data" colspan="5">%s</th></tr>',
437
                $this->lang['strlinksymbol']
438
            ) . \PHP_EOL;
439
            echo '<tr><td class="data1" colspan="5"><input type="text" name="formLinkSymbol" style="width:100%" value="',
440
            \htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>' . \PHP_EOL;
441
        } else {
442
            echo \sprintf(
443
                '<tr><th class="data required" colspan="5">%s</th></tr>',
444
                $this->lang['strdefinition']
445
            ) . \PHP_EOL;
446
            echo '<tr><td class="data1" colspan="5">';
447
            $textarea_id = ('sql' === $fnlang || 'plpgsql' === $fnlang) ? 'query' : 'formDefinition';
448
            echo '<textarea style="width:100%;" rows="20" cols="50" id="' . $textarea_id . '" name="formDefinition">';
449
            echo \htmlspecialchars($_POST['formDefinition']);
450
            echo '</textarea></td></tr>' . \PHP_EOL;
451
        }
452
453
        // Display function comment
454
        echo \sprintf(
455
            '<tr><th class="data" colspan="5">%s</th></tr>',
456
            $this->lang['strcomment']
457
        ) . \PHP_EOL;
458
        echo '<tr><td class="data1" colspan="5">';
459
        echo '<textarea style="width:100%;" name="formComment" rows="3" cols="50">';
460
        echo \htmlspecialchars($_POST['formComment']);
461
        echo '</textarea></td></tr>' . \PHP_EOL;
462
463
        // Display function cost options
464
        if ($data->hasFunctionCosting()) {
465
            echo \sprintf(
466
                '<tr><th class="data required" colspan="5">%s</th></tr>',
467
                $this->lang['strfunctioncosting']
468
            ) . \PHP_EOL;
469
            echo \sprintf(
470
                '<td class="data1" colspan="2">%s: <input name="formCost" size="16" value="',
471
                $this->lang['strexecutioncost']
472
            ) .
473
            \htmlspecialchars($_POST['formCost']) . '" /></td>';
474
            echo \sprintf(
475
                '<td class="data1" colspan="2">%s: <input name="formRows" size="16" value="',
476
                $this->lang['strresultrows']
477
            ),
478
            \htmlspecialchars($_POST['formRows']), '"', (!$fndata->fields['proretset']) ? 'disabled' : '', '/></td>';
479
        }
480
481
        // Display function properties
482
        if (\is_array($data->funcprops) && 0 < \count($data->funcprops)) {
483
            echo \sprintf(
484
                '<tr><th class="data" colspan="5">%s</th></tr>',
485
                $this->lang['strproperties']
486
            ) . \PHP_EOL;
487
            echo '<tr><td class="data1" colspan="5">' . \PHP_EOL;
488
            $i = 0;
489
490
            foreach ($data->funcprops as $k => $v) {
491
                echo \sprintf(
492
                    '<select name="formProperties[%s]">',
493
                    $i
494
                ) . \PHP_EOL;
495
496
                foreach ($v as $p) {
497
                    echo '<option value="', \htmlspecialchars($p), '"',
498
                    ($_POST['formProperties'][$i] === $p) ? ' selected="selected"' : '',
499
                    '>', $this->misc->printVal($p), '</option>' . \PHP_EOL;
500
                }
501
                echo '</select><br />' . \PHP_EOL;
502
                ++$i;
503
            }
504
            echo '</td></tr>' . \PHP_EOL;
505
        }
506
507
        // function owner
508
        if ($data->hasFunctionAlterOwner()) {
509
            $users = $data->getUsers();
510
            echo \sprintf(
511
                '<tr><td class="data1" colspan="5">%s: <select name="formFuncOwn">',
512
                $this->lang['strowner']
513
            );
514
515
            while (!$users->EOF) {
516
                $uname = $users->fields['usename'];
517
                echo '<option value="', \htmlspecialchars($uname), '"',
518
                ($uname === $_POST['formFuncOwn']) ? ' selected="selected"' : '', '>', \htmlspecialchars($uname), '</option>' . \PHP_EOL;
519
                $users->MoveNext();
520
            }
521
            echo '</select>' . \PHP_EOL;
522
            echo '<input type="hidden" name="original_owner" value="', \htmlspecialchars($fndata->fields['proowner']), '" />' . \PHP_EOL;
523
            echo '</td></tr>' . \PHP_EOL;
524
        }
525
        echo '</table>' . \PHP_EOL;
526
        echo '<p><input type="hidden" name="action" value="save_edit" />' . \PHP_EOL;
527
        echo '<input type="hidden" name="function" value="', \htmlspecialchars($_REQUEST['function']), '" />' . \PHP_EOL;
528
        echo '<input type="hidden" name="function_oid" value="', \htmlspecialchars($_REQUEST['function_oid']), '" />' . \PHP_EOL;
529
        echo $this->view->form;
530
        echo \sprintf(
531
            '<input type="submit" value="%s" />',
532
            $this->lang['stralter']
533
        ) . \PHP_EOL;
534
        echo \sprintf(
535
            '<input type="submit" name="cancel" value="%s"  /></p>%s',
536
            $this->lang['strcancel'],
537
            \PHP_EOL
538
        );
539
        echo '</form>' . \PHP_EOL;
540
    }
541
542
    /**
543
     * Show the creation sentence for this function.
544
     *
545
     * @param string $fname        The function name
546
     * @param int    $function_oid The function oid
547
     *
548
     * @return string the navlinks to print at the bottom
549
     */
550
    public function showDefinition($fname, $function_oid)
551
    {
552
        $data = $this->misc->getDatabaseAccessor();
553
554
        $this->printTrail('function');
555
        $this->printTabs('function', 'export');
556
        $this->printTitle($this->lang['strproperties'], 'pg.function');
557
558
        $fname = \str_replace(' ', '', $f);
559
        $funcdata = $data->getFunctionDef($function_oid);
560
        $func_full = '';
561
562
        if (0 >= $funcdata->RecordCount()) {
563
            echo \sprintf(
564
                '<p>%s</p>',
565
                $this->lang['strnodata']
566
            ) . \PHP_EOL;
567
568
            return $this->_printNavLinks('functions-properties', $func_full);
569
        }
570
571
        echo '<table style="width: 95%">' . \PHP_EOL;
572
573
        $fnlang = \mb_strtolower($funcdata->fields['prolanguage']);
574
        echo '<tr><td class="data1" colspan="4">';
575
        echo \sprintf(
576
            '<pre><code class="sql hljs">%s',
577
            \PHP_EOL
578
        );
579
580
        echo \sprintf(
581
            '%s--%s',
582
            \PHP_EOL,
583
            \PHP_EOL
584
        );
585
        echo \sprintf(
586
            '-- Name: %s; Type: FUNCTION; Schema: %s; Owner: %s',
587
            $fname,
588
            $funcdata->fields['nspname'],
589
            $funcdata->fields['relowner']
590
        );
591
        echo \sprintf(
592
            '%s--%s%s',
593
            \PHP_EOL,
594
            \PHP_EOL,
595
            \PHP_EOL
596
        );
597
598
        echo \sprintf(
599
            '%s;',
600
            $funcdata->fields['pg_get_functiondef']
601
        );
602
603
        echo \sprintf(
604
            '%s%sALTER FUNCTION %s OWNER TO %s;%s',
605
            \PHP_EOL,
606
            \PHP_EOL,
607
            $fname,
608
            $funcdata->fields['relowner'],
609
            \PHP_EOL
610
        );
611
612
        // Show comment if any
613
        if (null !== $funcdata->fields['relcomment']) {
614
            echo \sprintf(
615
                '%s--%s',
616
                \PHP_EOL,
617
                \PHP_EOL
618
            );
619
            echo \sprintf(
620
                '-- Name: %s; Type: COMMENT; Schema: %s; Owner: %s',
621
                $fname,
622
                $funcdata->fields['nspname'],
623
                $funcdata->fields['relowner']
624
            );
625
            echo \sprintf(
626
                '%s--%s%s',
627
                \PHP_EOL,
628
                \PHP_EOL,
629
                \PHP_EOL
630
            );
631
            echo \sprintf("%sCOMMENT ON FUNCTION %s.%s IS '%s';%s", \PHP_EOL, $funcdata->fields['nspname'], $fname, $funcdata->fields['relcomment'], \PHP_EOL);
632
            //echo '<p class="comment">', $this->misc->printVal($funcdata->fields['relcomment']), '</p>' . PHP_EOL;
633
        }
634
635
        echo \sprintf(
636
            '%s</code></pre>',
637
            \PHP_EOL
638
        );
639
640
        echo '</td></tr>' . \PHP_EOL;
641
642
        echo '</table>' . \PHP_EOL;
643
644
        return $this->_printNavLinks('functions-properties', $func_full);
645
    }
646
647
    /**
648
     * Show read only properties of a function.
649
     *
650
     * @param mixed $msg
651
     */
652
    public function doProperties($msg = '')
653
    {
654
        $data = $this->misc->getDatabaseAccessor();
655
656
        $this->printTrail('function');
657
        $this->printTabs('function', 'definition');
658
        $this->printTitle($this->lang['strproperties'], 'pg.function');
659
        $this->printMsg($msg);
660
661
        $funcdata = $data->getFunction($_REQUEST['function_oid']);
662
        $func_full = '';
663
664
        if (0 >= $funcdata->RecordCount()) {
665
            echo \sprintf(
666
                '<p>%s</p>',
667
                $this->lang['strnodata']
668
            ) . \PHP_EOL;
669
670
            return $this->_printNavLinks('functions-properties', $func_full);
671
        }
672
        // Deal with named parameters
673
        $args = $this->_getPropertiesArgs($funcdata);
674
675
        // Show comment if any
676
        if (null !== $funcdata->fields['procomment']) {
677
            echo '<p class="comment">', $this->misc->printVal($funcdata->fields['procomment']), '</p>' . \PHP_EOL;
678
        }
679
680
        $funcdata->fields['proretset'] = $data->phpBool($funcdata->fields['proretset']);
681
        $func_full = $funcdata->fields['proname'] . '(' . $funcdata->fields['proarguments'] . ')';
682
683
        echo '<table style="width: 95%">' . \PHP_EOL;
684
685
        echo \sprintf(
686
            '<tr><th class="data">%s</th>%s',
687
            $this->lang['strfunction'],
688
            \PHP_EOL
689
        );
690
        echo \sprintf(
691
            '<th class="data">%s</th>%s',
692
            $this->lang['strarguments'],
693
            \PHP_EOL
694
        );
695
        echo \sprintf(
696
            '<th class="data">%s</th>%s',
697
            $this->lang['strreturns'],
698
            \PHP_EOL
699
        );
700
        echo \sprintf(
701
            '<th class="data">%s</th></tr>%s',
702
            $this->lang['strproglanguage'],
703
            \PHP_EOL
704
        );
705
706
        echo '<tr><td class="data1">', $this->misc->printVal($funcdata->fields['proname']), '</td>' . \PHP_EOL;
707
        echo '<td class="data1">', $this->misc->printVal($args), '</td>' . \PHP_EOL;
708
        echo '<td class="data1">';
709
710
        if ($funcdata->fields['proretset']) {
711
            echo 'setof ';
712
        }
713
714
        echo $this->misc->printVal($funcdata->fields['proresult']), '</td>' . \PHP_EOL;
715
        echo '<td class="data1">', $this->misc->printVal($funcdata->fields['prolanguage']), '</td></tr>' . \PHP_EOL;
716
717
        $fnlang = \mb_strtolower($funcdata->fields['prolanguage']);
718
719
        if ('c' === $fnlang) {
720
            echo \sprintf(
721
                '<tr><th class="data" colspan="2">%s</th>',
722
                $this->lang['strobjectfile']
723
            ) . \PHP_EOL;
724
            echo \sprintf(
725
                '<th class="data" colspan="2">%s</th></tr>',
726
                $this->lang['strlinksymbol']
727
            ) . \PHP_EOL;
728
            echo '<tr><td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['probin']), '</td>' . \PHP_EOL;
729
            echo '<td class="data1" colspan="2">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>' . \PHP_EOL;
730
        } elseif ('internal' === $fnlang) {
731
            echo \sprintf(
732
                '<tr><th class="data" colspan="4">%s</th></tr>',
733
                $this->lang['strlinksymbol']
734
            ) . \PHP_EOL;
735
            echo '<tr><td class="data1" colspan="4">', $this->misc->printVal($funcdata->fields['prosrc']), '</td></tr>' . \PHP_EOL;
736
        } else {
737
            echo '<tr><td class="data1" colspan="4">';
738
            echo \sprintf(
739
                '<pre><code class="%s hljs">%s</code></pre>',
740
                $fnlang,
741
                $funcdata->fields['prosrc']
742
            );
743
            echo '</td></tr>' . \PHP_EOL;
744
        }
745
746
        // Display function cost options
747
        if ($data->hasFunctionCosting()) {
748
            echo \sprintf(
749
                '<tr><th class="data required" colspan="4">%s</th></tr>',
750
                $this->lang['strfunctioncosting']
751
            ) . \PHP_EOL;
752
            echo \sprintf(
753
                '<td class="data1" colspan="2">%s: ',
754
                $this->lang['strexecutioncost']
755
            ), $this->misc->printVal($funcdata->fields['procost']), ' </td>';
756
            echo \sprintf(
757
                '<td class="data1" colspan="2">%s: ',
758
                $this->lang['strresultrows']
759
            ), $this->misc->printVal($funcdata->fields['prorows']), ' </td>';
760
        }
761
762
        // Show flags
763
        if (\is_array($data->funcprops) && 0 < \count($data->funcprops)) {
764
            // Fetch an array of the function properties
765
            $funcprops = $data->getFunctionProperties($funcdata->fields);
766
            echo \sprintf(
767
                '<tr><th class="data" colspan="4">%s</th></tr>',
768
                $this->lang['strproperties']
769
            ) . \PHP_EOL;
770
            echo '<tr><td class="data1" colspan="4">' . \PHP_EOL;
771
772
            foreach ($funcprops as $v) {
773
                echo $this->misc->printVal($v), '<br />' . \PHP_EOL;
774
            }
775
            echo '</td></tr>' . \PHP_EOL;
776
        }
777
778
        echo \sprintf(
779
            '<tr><td class="data1" colspan="5">%s: ',
780
            $this->lang['strowner']
781
        ), \htmlspecialchars($funcdata->fields['proowner']), \PHP_EOL;
782
        echo '</td></tr>' . \PHP_EOL;
783
        echo '</table>' . \PHP_EOL;
784
785
        return $this->_printNavLinks('functions-properties', $func_full);
786
    }
787
788
    /**
789
     * Show confirmation of drop and perform actual drop.
790
     *
791
     * @param mixed $confirm
792
     */
793
    public function doDrop($confirm)
794
    {
795
        $data = $this->misc->getDatabaseAccessor();
796
797
        if (empty($_REQUEST['function']) && empty($_REQUEST['ma'])) {
798
            return $this->doDefault($this->lang['strspecifyfunctiontodrop']);
799
        }
800
801
        if ($confirm) {
802
            $this->printTrail('function');
803
            $this->printTabs('function', 'definition');
804
            $this->printTitle($this->lang['strdrop'], 'pg.function.drop');
805
806
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/functions" method="post">' . \PHP_EOL;
807
808
            //If multi drop
809
            if (isset($_REQUEST['ma'])) {
810
                foreach ($_REQUEST['ma'] as $v) {
811
                    $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
812
                    echo '<p>', \sprintf(
813
                        $this->lang['strconfdropfunction'],
814
                        $this->misc->printVal($a['function'])
815
                    ), '</p>' . \PHP_EOL;
816
                    echo '<input type="hidden" name="function[]" value="', \htmlspecialchars($a['function']), '" />' . \PHP_EOL;
817
                    echo '<input type="hidden" name="function_oid[]" value="', \htmlspecialchars($a['function_oid']), '" />' . \PHP_EOL;
818
                }
819
            } else {
820
                echo '<p>', \sprintf(
821
                    $this->lang['strconfdropfunction'],
822
                    $this->misc->printVal($_REQUEST['function'])
823
                ), '</p>' . \PHP_EOL;
824
                echo '<input type="hidden" name="function" value="', \htmlspecialchars($_REQUEST['function']), '" />' . \PHP_EOL;
825
                echo '<input type="hidden" name="function_oid" value="', \htmlspecialchars($_REQUEST['function_oid']), '" />' . \PHP_EOL;
826
            }
827
828
            echo '<input type="hidden" name="action" value="drop" />' . \PHP_EOL;
829
830
            echo $this->view->form;
831
            echo \sprintf(
832
                '<p><input type="checkbox" id="cascade" name="cascade" /><label for="cascade">%s</label></p>',
833
                $this->lang['strcascade']
834
            ) . \PHP_EOL;
835
            echo \sprintf(
836
                '<input type="submit" name="drop" value="%s" />',
837
                $this->lang['strdrop']
838
            ) . \PHP_EOL;
839
            echo \sprintf(
840
                '<input type="submit" name="cancel" value="%s" />',
841
                $this->lang['strcancel']
842
            ) . \PHP_EOL;
843
            echo '</form>' . \PHP_EOL;
844
        } else {
845
            if (\is_array($_POST['function_oid'])) {
846
                $msg = '';
847
                $status = $data->beginTransaction();
848
849
                if (0 === $status) {
850
                    foreach ($_POST['function_oid'] as $k => $s) {
851
                        $status = $data->dropFunction($s, isset($_POST['cascade']));
852
853
                        if (0 === $status) {
854
                            $msg .= \sprintf(
855
                                '%s: %s<br />',
856
                                \htmlentities($_POST['function'][$k], \ENT_QUOTES, 'UTF-8'),
857
                                $this->lang['strfunctiondropped']
858
                            );
859
                        } else {
860
                            $data->endTransaction();
861
                            $this->doDefault(\sprintf(
862
                                '%s%s: %s<br />',
863
                                $msg,
864
                                \htmlentities($_POST['function'][$k], \ENT_QUOTES, 'UTF-8'),
865
                                $this->lang['strfunctiondroppedbad']
866
                            ));
867
868
                            return;
869
                        }
870
                    }
871
                }
872
873
                if (0 === $data->endTransaction()) {
874
                    // Everything went fine, back to the Default page....
875
                    $this->view->setReloadBrowser(true);
876
                    $this->doDefault($msg);
877
                } else {
878
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
879
                }
880
            } else {
881
                $status = $data->dropFunction($_POST['function_oid'], isset($_POST['cascade']));
882
883
                if (0 === $status) {
884
                    $this->view->setReloadBrowser(true);
885
                    $this->doDefault($this->lang['strfunctiondropped']);
886
                } else {
887
                    $this->doDefault($this->lang['strfunctiondroppedbad']);
888
                }
889
            }
890
        }
891
    }
892
893
    /**
894
     * Displays a screen where they can enter a new function.
895
     *
896
     * @param string $msg  message to display
897
     * @param mixed  $szJS
898
     */
899
    public function doCreate($msg = '', $szJS = ''): void
900
    {
901
        $data = $this->misc->getDatabaseAccessor();
902
903
        $this->printTrail('schema');
904
        $_POST['formFunction'] = $this->getPostParam('formFunction', '');
905
906
        $_POST['formArguments'] = $this->getPostParam('formArguments', '');
907
908
        $_POST['formReturns'] = $this->getPostParam('formReturns', '');
909
910
        $this->coalesceArr($_POST, 'formLanguage', $_REQUEST['language'] ?? 'sql');
911
912
        $_POST['formDefinition'] = $this->getPostParam('formDefinition', '');
913
914
        $_POST['formObjectFile'] = $this->getPostParam('formObjectFile', '');
915
916
        $_POST['formLinkSymbol'] = $this->getPostParam('formLinkSymbol', '');
917
918
        $_POST['formProperties'] = $this->getPostParam('formProperties', $data->defaultprops);
919
920
        $_POST['formSetOf'] = $this->getPostParam('formSetOf', '');
921
922
        $_POST['formArray'] = $this->getPostParam('formArray', '');
923
924
        $_POST['formCost'] = $this->getPostParam('formCost', '');
925
926
        $_POST['formRows'] = $this->getPostParam('formRows', '');
927
928
        $_POST['formComment'] = $this->getPostParam('formComment', '');
929
930
        $types = $data->getTypes(true, true, true);
931
        $langs = $data->getLanguages(true);
932
        $fnlang = \mb_strtolower($_POST['formLanguage']);
933
934
        switch ($fnlang) {
935
            case 'c':
936
                $this->printTitle($this->lang['strcreatecfunction'], 'pg.function.create.c');
937
938
                break;
939
            case 'internal':
940
                $this->printTitle($this->lang['strcreateinternalfunction'], 'pg.function.create.internal');
941
942
                break;
943
944
            default:
945
                $this->printTitle($this->lang['strcreateplfunction'], 'pg.function.create.pl');
946
947
                break;
948
        }
949
        $this->printMsg($msg);
950
951
        // Create string for return type list
952
        $szTypes = '';
953
954
        while (!$types->EOF) {
955
            $szSelected = '';
956
957
            if ($types->fields['typname'] === $_POST['formReturns']) {
958
                $szSelected = ' selected="selected"';
959
            }
960
            // this variable is include in the JS code bellow, so we need to ENT_QUOTES
961
            $szTypes .= '<option value="' . \htmlspecialchars($types->fields['typname'], \ENT_QUOTES) . \sprintf(
962
                '"%s>',
963
                $szSelected
964
            );
965
            $szTypes .= \htmlspecialchars($types->fields['typname'], \ENT_QUOTES) . '</option>';
966
            $types->MoveNext();
967
        }
968
969
        $szFunctionName = \sprintf(
970
            '<td class="data1"><input name="formFunction" size="16" maxlength="%s" value="',
971
            $data->_maxNameLen
972
        ) .
973
        \htmlspecialchars($_POST['formFunction']) . '" /></td>';
974
975
        $szArguments = '<td class="data1"><input name="formArguments" style="width:100%;" size="16" value="' .
976
        \htmlspecialchars($_POST['formArguments']) . '" /></td>';
977
978
        $szSetOfSelected = '';
979
        $szNotSetOfSelected = '';
980
981
        if ('' === $_POST['formSetOf']) {
982
            $szNotSetOfSelected = ' selected="selected"';
983
        } elseif ('SETOF' === $_POST['formSetOf']) {
984
            $szSetOfSelected = ' selected="selected"';
985
        }
986
        $szReturns = '<td class="data1" colspan="2">';
987
        $szReturns .= '<select name="formSetOf">';
988
        $szReturns .= \sprintf(
989
            '<option value=""%s></option>',
990
            $szNotSetOfSelected
991
        );
992
        $szReturns .= \sprintf(
993
            '<option value="SETOF"%s>SETOF</option>',
994
            $szSetOfSelected
995
        );
996
        $szReturns .= '</select>';
997
998
        $szReturns .= '<select class="select2" name="formReturns">' . $szTypes . '</select>';
999
1000
        // Create string array type selector
1001
1002
        $szArraySelected = '';
1003
        $szNotArraySelected = '';
1004
1005
        if ('' === $_POST['formArray']) {
1006
            $szNotArraySelected = ' selected="selected"';
1007
        } elseif ('[]' === $_POST['formArray']) {
1008
            $szArraySelected = ' selected="selected"';
1009
        }
1010
1011
        $szReturns .= '<select name="formArray">';
1012
        $szReturns .= \sprintf(
1013
            '<option value=""%s></option>',
1014
            $szNotArraySelected
1015
        );
1016
        $szReturns .= \sprintf(
1017
            '<option value="[]"%s>[ ]</option>',
1018
            $szArraySelected
1019
        );
1020
        $szReturns .= "</select>\n</td>";
1021
1022
        // Create string for language
1023
        $szLanguage = '<td class="data1">';
1024
1025
        if ('c' === $fnlang || 'internal' === $fnlang) {
1026
            $szLanguage .= $_POST['formLanguage'] . \PHP_EOL;
1027
            $szLanguage .= \sprintf(
1028
                '<input type="hidden" name="formLanguage" value="%s" />',
1029
                $_POST['formLanguage']
1030
            ) . \PHP_EOL;
1031
        } else {
1032
            $szLanguage .= '<select name="formLanguage">' . \PHP_EOL;
1033
1034
            while (!$langs->EOF) {
1035
                $szSelected = '';
1036
1037
                if ($langs->fields['lanname'] === $_POST['formLanguage']) {
1038
                    $szSelected = ' selected="selected"';
1039
                }
1040
1041
                if ('c' !== \mb_strtolower($langs->fields['lanname']) && 'internal' !== \mb_strtolower($langs->fields['lanname'])) {
1042
                    $szLanguage .= '<option value="' . \htmlspecialchars($langs->fields['lanname']) . \sprintf(
1043
                        '"%s>
1044
',
1045
                        $szSelected
1046
                    ) .
1047
                    $this->misc->printVal($langs->fields['lanname']) . '</option>';
1048
                }
1049
1050
                $langs->MoveNext();
1051
            }
1052
            $szLanguage .= '</select>' . \PHP_EOL;
1053
        }
1054
1055
        $szLanguage .= '</td>';
1056
        $szJSArguments = \sprintf(
1057
            '<tr><th class="data" colspan="7">%s</th></tr>',
1058
            $this->lang['strarguments']
1059
        );
1060
        $arrayModes = ['IN', 'OUT', 'INOUT'];
1061
        $szModes = '<select name="formArgModes[]" style="width:100%;">';
1062
1063
        foreach ($arrayModes as $pV) {
1064
            $szModes .= \sprintf(
1065
                '<option value="%s">%s</option>',
1066
                $pV,
1067
                $pV
1068
            );
1069
        }
1070
        $szModes .= '</select>';
1071
        $szArgReturns = '<select name="formArgArray[]">';
1072
        $szArgReturns .= '<option value=""></option>';
1073
        $szArgReturns .= '<option value="[]">[]</option>';
1074
        $szArgReturns .= '</select>';
1075
        $subfolder = \containerInstance()->subFolder;
1076
1077
        if (!empty($this->conf['theme'])) {
1078
            $szImgPath = \containerInstance()->subFolder . \sprintf(
1079
                '/assets/images/themes/%s',
1080
                $this->conf['theme']
1081
            );
1082
        } else {
1083
            $szImgPath = \containerInstance()->subFolder . '/assets/images/themes/default';
1084
        }
1085
1086
        if (empty($msg)) {
1087
            $szJSTRArg = \sprintf(
1088
                '<script type="text/javascript" >addArg(\'%s\');</script>',
1089
                $subfolder
1090
            ) . \PHP_EOL;
1091
        } else {
1092
            $szJSTRArg = '';
1093
        }
1094
        $szJSAddTR = \sprintf(
1095
            '<tr id="parent_add_tr" onclick="addArg(\'%s\');" onmouseover="this.style.cursor=\'pointer\'">',
1096
            $subfolder
1097
        ) . \PHP_EOL;
1098
        $szJSAddTR .= '<td style="text-align: right" colspan="6" class="data3"><table><tr><td class="data3">';
1099
        $szJSAddTR .= \sprintf(
1100
            '<img src="%s/AddArguments.png" alt="Add Argument" /></td>',
1101
            $szImgPath
1102
        );
1103
        $szJSAddTR .= \sprintf(
1104
            '<td class="data3"><span style="font-size: 8pt">%s</span></td></tr></table></td>
1105
</tr>',
1106
            $this->lang['strargadd']
1107
        ) . \PHP_EOL;
1108
1109
        echo '<script src="' . \containerInstance()->subFolder . \sprintf(
1110
            '/assets/js/functions.js" type="text/javascript"></script>
1111
		<script type="text/javascript">
1112
			//<![CDATA[
1113
			var g_types_select = \'<select class="select2" name="formArgType[]">%s</select>%s\';
1114
			var g_modes_select = \'%s\';
1115
			var g_name = \'\';
1116
			var g_lang_strargremove = \'',
1117
            $szTypes,
1118
            $szArgReturns,
1119
            $szModes
1120
        ), \htmlspecialchars($this->lang['strargremove'], \ENT_QUOTES), "';
1121
			var g_lang_strargnoargs = '", \htmlspecialchars($this->lang['strargnoargs'], \ENT_QUOTES), "';
1122
			var g_lang_strargenableargs = '", \htmlspecialchars($this->lang['strargenableargs'], \ENT_QUOTES), "';
1123
			var g_lang_strargnorowabove = '", \htmlspecialchars($this->lang['strargnorowabove'], \ENT_QUOTES), "';
1124
			var g_lang_strargnorowbelow = '", \htmlspecialchars($this->lang['strargnorowbelow'], \ENT_QUOTES), "';
1125
			var g_lang_strargremoveconfirm = '", \htmlspecialchars($this->lang['strargremoveconfirm'], \ENT_QUOTES), "';
1126
			var g_lang_strargraise = '", \htmlspecialchars($this->lang['strargraise'], \ENT_QUOTES), "';
1127
			var g_lang_strarglower = '", \htmlspecialchars($this->lang['strarglower'], \ENT_QUOTES), "';
1128
			//]]>
1129
		</script>
1130
		";
1131
        echo '<form action="' . \containerInstance()->subFolder . '/src/views/functions" method="post">' . \PHP_EOL;
1132
        echo '<table><tbody id="args_table">' . \PHP_EOL;
1133
        echo \sprintf(
1134
            '<tr><th class="data required">%s</th>',
1135
            $this->lang['strname']
1136
        ) . \PHP_EOL;
1137
        echo \sprintf(
1138
            '<th class="data required" colspan="2">%s</th>',
1139
            $this->lang['strreturns']
1140
        ) . \PHP_EOL;
1141
        echo \sprintf(
1142
            '<th class="data required">%s</th></tr>',
1143
            $this->lang['strproglanguage']
1144
        ) . \PHP_EOL;
1145
        echo '<tr>' . \PHP_EOL;
1146
        echo $szFunctionName . \PHP_EOL;
1147
        echo $szReturns . \PHP_EOL;
1148
        echo $szLanguage . \PHP_EOL;
1149
        echo '</tr>' . \PHP_EOL;
1150
        echo $szJSArguments . \PHP_EOL;
1151
        echo '<tr>' . \PHP_EOL;
1152
        echo \sprintf(
1153
            '<th class="data required">%s</th>',
1154
            $this->lang['strargmode']
1155
        ) . \PHP_EOL;
1156
        echo \sprintf(
1157
            '<th class="data required">%s</th>',
1158
            $this->lang['strname']
1159
        ) . \PHP_EOL;
1160
        echo \sprintf(
1161
            '<th class="data required" colspan="2">%s</th>',
1162
            $this->lang['strargtype']
1163
        ) . \PHP_EOL;
1164
        echo '</tr>' . \PHP_EOL;
1165
        echo $szJSAddTR . \PHP_EOL;
1166
1167
        if ('c' === $fnlang) {
1168
            echo \sprintf(
1169
                '<tr><th class="data required" colspan="2">%s</th>',
1170
                $this->lang['strobjectfile']
1171
            ) . \PHP_EOL;
1172
            echo \sprintf(
1173
                '<th class="data" colspan="2">%s</th></tr>',
1174
                $this->lang['strlinksymbol']
1175
            ) . \PHP_EOL;
1176
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
1177
            \htmlspecialchars($_POST['formObjectFile']), '" /></td>' . \PHP_EOL;
1178
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1179
            \htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>' . \PHP_EOL;
1180
        } elseif ('internal' === $fnlang) {
1181
            echo \sprintf(
1182
                '<tr><th class="data" colspan="4">%s</th></tr>',
1183
                $this->lang['strlinksymbol']
1184
            ) . \PHP_EOL;
1185
            echo '<tr><td class="data1" colspan="4"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1186
            \htmlspecialchars($_POST['formLinkSymbol']), '" /></td></tr>' . \PHP_EOL;
1187
        } else {
1188
            echo \sprintf(
1189
                '<tr><th class="data required" colspan="4">%s</th></tr>',
1190
                $this->lang['strdefinition']
1191
            ) . \PHP_EOL;
1192
            echo '<tr><td class="data1" colspan="4">';
1193
            echo '<textarea style="width:100%;" rows="20" cols="50" name="formDefinition">';
1194
            echo \htmlspecialchars($_POST['formDefinition']);
1195
            echo '</textarea></td></tr>' . \PHP_EOL;
1196
        }
1197
1198
        // Display function comment
1199
        echo \sprintf(
1200
            '<tr><th class="data" colspan="4">%s</th></tr>',
1201
            $this->lang['strcomment']
1202
        ) . \PHP_EOL;
1203
        echo '<tr><td class="data1" colspan="4"><textarea style="width:100%;" name="formComment" rows="3" cols="50">',
1204
        \htmlspecialchars($_POST['formComment']), '</textarea></td></tr>' . \PHP_EOL;
1205
1206
        // Display function cost options
1207
        if ($data->hasFunctionCosting()) {
1208
            echo \sprintf(
1209
                '<tr><th class="data required" colspan="4">%s</th></tr>',
1210
                $this->lang['strfunctioncosting']
1211
            ) . \PHP_EOL;
1212
            echo \sprintf(
1213
                '<td class="data1" colspan="2">%s: <input name="formCost" size="16" value="',
1214
                $this->lang['strexecutioncost']
1215
            ) .
1216
            \htmlspecialchars($_POST['formCost']) . '" /></td>';
1217
            echo \sprintf(
1218
                '<td class="data1" colspan="2">%s: <input name="formRows" size="16" value="',
1219
                $this->lang['strresultrows']
1220
            ) .
1221
            \htmlspecialchars($_POST['formRows']) . '" /></td>';
1222
        }
1223
1224
        // Display function properties
1225
        if (\is_array($data->funcprops) && 0 < \count($data->funcprops)) {
1226
            echo \sprintf(
1227
                '<tr><th class="data required" colspan="4">%s</th></tr>',
1228
                $this->lang['strproperties']
1229
            ) . \PHP_EOL;
1230
            echo '<tr><td class="data1" colspan="4">' . \PHP_EOL;
1231
            $i = 0;
1232
1233
            foreach ($data->funcprops as $k => $v) {
1234
                echo \sprintf(
1235
                    '<select name="formProperties[%s]">',
1236
                    $i
1237
                ) . \PHP_EOL;
1238
1239
                foreach ($v as $p) {
1240
                    echo '<option value="', \htmlspecialchars($p), '"',
1241
                    ($_POST['formProperties'][$i] === $p) ? ' selected="selected"' : '',
1242
                    '>', $this->misc->printVal($p), '</option>' . \PHP_EOL;
1243
                }
1244
                echo '</select><br />' . \PHP_EOL;
1245
                ++$i;
1246
            }
1247
            echo '</td></tr>' . \PHP_EOL;
1248
        }
1249
        echo '</tbody></table>' . \PHP_EOL;
1250
        echo $szJSTRArg;
1251
        echo '<p><input type="hidden" name="action" value="save_create" />' . \PHP_EOL;
1252
        echo $this->view->form;
1253
        echo \sprintf(
1254
            '<input type="submit" value="%s" />',
1255
            $this->lang['strcreate']
1256
        ) . \PHP_EOL;
1257
        echo \sprintf(
1258
            '<input type="submit" name="cancel" value="%s"  /></p>%s',
1259
            $this->lang['strcancel'],
1260
            \PHP_EOL
1261
        );
1262
        echo '</form>' . \PHP_EOL;
1263
        echo $szJS;
1264
    }
1265
1266
    /**
1267
     * Actually creates the new function in the database.
1268
     */
1269
    public function doSaveCreate(): void
1270
    {
1271
        $data = $this->misc->getDatabaseAccessor();
1272
1273
        $fnlang = \mb_strtolower($_POST['formLanguage']);
1274
1275
        if ('c' === $fnlang) {
1276
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
1277
        } elseif ('internal' === $fnlang) {
1278
            $def = $_POST['formLinkSymbol'];
1279
        } else {
1280
            $def = $_POST['formDefinition'];
1281
        }
1282
1283
        $szJS = '';
1284
1285
        echo '<script src="' . \containerInstance()->subFolder . '/assets/js/functions.js" type="text/javascript"></script>';
1286
        echo '<script type="text/javascript">' . $this->_buildJSData() . '</script>';
1287
1288
        if (!empty($_POST['formArgName'])) {
1289
            $szJS = $this->_buildJSRows($this->_buildFunctionArguments($_POST));
1290
        } else {
1291
            $subfolder = \containerInstance()->subFolder;
1292
            $szJS = '<script type="text/javascript" src="' . \containerInstance()->subFolder . '/assets/js/functions.js">noArgsRebuild(addArg("' . $subfolder . '"));</script>';
1293
        }
1294
1295
        $cost = (isset($_POST['formCost'])) ? $_POST['formCost'] : null;
1296
1297
        if ('' === $cost || !\is_numeric($cost) || (int) $cost !== $cost || 0 > $cost) {
1298
            $cost = null;
1299
        }
1300
1301
        $rows = (isset($_POST['formRows'])) ? $_POST['formRows'] : null;
1302
1303
        if ('' === $rows || !\is_numeric($rows) || (int) $rows !== $rows) {
1304
            $rows = null;
1305
        }
1306
1307
        // Check that they've given a name and a definition
1308
        if ('' === $_POST['formFunction']) {
1309
            $this->doCreate($this->lang['strfunctionneedsname'], $szJS);
1310
        } elseif ('internal' !== $fnlang && !$def) {
1311
            $this->doCreate($this->lang['strfunctionneedsdef'], $szJS);
1312
        } else {
1313
            // Append array symbol to type if chosen
1314
            $status = $data->createFunction(
1315
                $_POST['formFunction'],
1316
                empty($_POST['nojs']) ? $this->_buildFunctionArguments($_POST) : $_POST['formArguments'],
1317
                $_POST['formReturns'] . $_POST['formArray'],
1318
                $def,
1319
                $_POST['formLanguage'],
1320
                $_POST['formProperties'],
1321
                'SETOF' === $_POST['formSetOf'],
1322
                $cost,
1323
                $rows,
1324
                $_POST['formComment'],
1325
                false
1326
            );
1327
1328
            if (0 === $status) {
1329
                $this->doDefault($this->lang['strfunctioncreated']);
1330
            } else {
1331
                $this->doCreate($this->lang['strfunctioncreatedbad'], $szJS);
1332
            }
1333
        }
1334
    }
1335
1336
    private function _printNavLinks(string $place, string $func_full = ''): void
1337
    {
1338
        if ('functions-properties' === $place) {
1339
            $navlinks = [
1340
                'showall' => [
1341
                    'attr' => [
1342
                        'href' => [
1343
                            'url' => 'functions',
1344
                            'urlvars' => [
1345
                                'server' => $_REQUEST['server'],
1346
                                'database' => $_REQUEST['database'],
1347
                                'schema' => $_REQUEST['schema'],
1348
                            ],
1349
                        ],
1350
                    ],
1351
                    'content' => $this->lang['strshowallfunctions'],
1352
                ],
1353
                'alter' => [
1354
                    'attr' => [
1355
                        'href' => [
1356
                            'url' => 'functions',
1357
                            'urlvars' => [
1358
                                'action' => 'edit',
1359
                                'server' => $_REQUEST['server'],
1360
                                'database' => $_REQUEST['database'],
1361
                                'schema' => $_REQUEST['schema'],
1362
                                'function' => $_REQUEST['function'],
1363
                                'function_oid' => $_REQUEST['function_oid'],
1364
                            ],
1365
                        ],
1366
                    ],
1367
                    'content' => $this->lang['stralter'],
1368
                ],
1369
                'drop' => [
1370
                    'attr' => [
1371
                        'href' => [
1372
                            'url' => 'functions',
1373
                            'urlvars' => [
1374
                                'action' => 'confirm_drop',
1375
                                'server' => $_REQUEST['server'],
1376
                                'database' => $_REQUEST['database'],
1377
                                'schema' => $_REQUEST['schema'],
1378
                                'function' => $func_full,
1379
                                'function_oid' => $_REQUEST['function_oid'],
1380
                            ],
1381
                        ],
1382
                    ],
1383
                    'content' => $this->lang['strdrop'],
1384
                ],
1385
            ];
1386
        } elseif ('functions-functions' === $place) {
1387
            $navlinks = [
1388
                'createpl' => [
1389
                    'attr' => [
1390
                        'href' => [
1391
                            'url' => 'functions',
1392
                            'urlvars' => [
1393
                                'action' => 'create',
1394
                                'server' => $_REQUEST['server'],
1395
                                'database' => $_REQUEST['database'],
1396
                                'schema' => $_REQUEST['schema'],
1397
                            ],
1398
                        ],
1399
                    ],
1400
                    'content' => $this->lang['strcreateplfunction'],
1401
                ],
1402
                'createinternal' => [
1403
                    'attr' => [
1404
                        'href' => [
1405
                            'url' => 'functions',
1406
                            'urlvars' => [
1407
                                'action' => 'create',
1408
                                'language' => 'internal',
1409
                                'server' => $_REQUEST['server'],
1410
                                'database' => $_REQUEST['database'],
1411
                                'schema' => $_REQUEST['schema'],
1412
                            ],
1413
                        ],
1414
                    ],
1415
                    'content' => $this->lang['strcreateinternalfunction'],
1416
                ],
1417
                'createc' => [
1418
                    'attr' => [
1419
                        'href' => [
1420
                            'url' => 'functions',
1421
                            'urlvars' => [
1422
                                'action' => 'create',
1423
                                'language' => 'C',
1424
                                'server' => $_REQUEST['server'],
1425
                                'database' => $_REQUEST['database'],
1426
                                'schema' => $_REQUEST['schema'],
1427
                            ],
1428
                        ],
1429
                    ],
1430
                    'content' => $this->lang['strcreatecfunction'],
1431
                ],
1432
            ];
1433
        } else {
1434
            return;
1435
        }
1436
1437
        $this->printNavLinks($navlinks, $place, \get_defined_vars());
1438
    }
1439
1440
    /**
1441
     * @param mixed $data
1442
     * @param mixed $fndata
1443
     *
1444
     * @return string
1445
     */
1446
    private function _getNamedParamsArgs($data, $fndata)
1447
    {
1448
        if (isset($fndata->fields['proallarguments'])) {
1449
            $args_arr = $data->phpArray($fndata->fields['proallarguments']);
1450
        } else {
1451
            $args_arr = \explode(', ', $fndata->fields['proarguments']);
1452
        }
1453
        $names_arr = $data->phpArray($fndata->fields['proargnames']);
1454
        $modes_arr = $data->phpArray($fndata->fields['proargmodes']);
1455
        $args = '';
1456
        $args_arr_size = \count($args_arr);
1457
1458
        for ($i = 0; $i < $args_arr_size; ++$i) {
1459
            if (0 !== $i) {
1460
                $args .= ', ';
1461
            }
1462
1463
            if (isset($modes_arr[$i])) {
1464
                switch ($modes_arr[$i]) {
1465
                    case 'i':
1466
                        $args .= ' IN ';
1467
1468
                        break;
1469
                    case 'o':
1470
                        $args .= ' OUT ';
1471
1472
                        break;
1473
                    case 'b':
1474
                        $args .= ' INOUT ';
1475
1476
                        break;
1477
                    case 'v':
1478
                        $args .= ' VARIADIC ';
1479
1480
                        break;
1481
                    case 't':
1482
                        $args .= ' TABLE ';
1483
1484
                        break;
1485
                }
1486
            }
1487
1488
            if (isset($names_arr[$i]) && '' !== $names_arr[$i]) {
1489
                $data->fieldClean($names_arr[$i]);
1490
                $args .= '"' . $names_arr[$i] . '" ';
1491
            }
1492
            $args .= $args_arr[$i];
1493
        }
1494
1495
        return $args;
1496
    }
1497
1498
    /**
1499
     * Build out the function arguments string.
1500
     *
1501
     * @param array $arrayVars
1502
     *
1503
     * @return string the imploded array vars
1504
     */
1505
    private function _buildFunctionArguments($arrayVars)
1506
    {
1507
        if (isset($_POST['formArgName'])) {
1508
            $arrayArgs = [];
1509
1510
            foreach ($arrayVars['formArgName'] as $pK => $pV) {
1511
                $arrayArgs[] = $arrayVars['formArgModes'][$pK] . ' ' . \trim($pV) . ' ' . \trim($arrayVars['formArgType'][$pK]) . $arrayVars['formArgArray'][$pK];
1512
            }
1513
1514
            return \implode(',', $arrayArgs);
1515
        }
1516
1517
        return '';
1518
    }
1519
1520
    /**
1521
     * Build out JS to re-create table rows for arguments.
1522
     *
1523
     * @param string $szArgs args to parse
1524
     *
1525
     * @return string
1526
     */
1527
    private function _buildJSRows($szArgs)
1528
    {
1529
        $arrayModes = ['IN', 'OUT', 'INOUT'];
1530
        $arrayArgs = \explode(',', $szArgs);
1531
        $arrayProperArgs = [];
1532
        $nC = 0;
1533
        $szReturn = '';
1534
        $szMode = [];
1535
1536
        foreach ($arrayArgs as $pV) {
1537
            $arrayWords = \explode(' ', $pV);
1538
1539
            if (true === \in_array($arrayWords[0], $arrayModes, true)) {
1540
                $szMode = $arrayWords[0];
1541
                \array_shift($arrayWords);
1542
            }
1543
            $szArgName = \array_shift($arrayWords);
1544
1545
            if (false === \mb_strpos($arrayWords[\count($arrayWords) - 1], '[]')) {
1546
                $szArgType = \implode(' ', $arrayWords);
1547
                $bArgIsArray = 'false';
1548
            } else {
1549
                $szArgType = \str_replace('[]', '', \implode(' ', $arrayWords));
1550
                $bArgIsArray = 'true';
1551
            }
1552
            $arrayProperArgs[] = [$szMode, $szArgName, $szArgType, $bArgIsArray];
1553
            $subfolder = \containerInstance()->subFolder;
1554
            $szReturn .= '<script type="text/javascript">';
1555
            $szReturn .= \sprintf(
1556
                'RebuildArgTR(\'%s\',\'%s\',\'%s\',new Boolean(%s,%s));',
1557
                $szMode,
1558
                $szArgName,
1559
                $szArgType,
1560
                $bArgIsArray,
1561
                $subfolder
1562
            );
1563
            $szReturn .= '</script>;';
1564
            ++$nC;
1565
        }
1566
1567
        return $szReturn;
1568
    }
1569
1570
    /**
1571
     * @return string
1572
     */
1573
    private function _buildJSData()
1574
    {
1575
        $data = $this->misc->getDatabaseAccessor();
1576
1577
        $arrayModes = ['IN', 'OUT', 'INOUT'];
1578
        $arrayTypes = $data->getTypes(true, true, true);
1579
        $arrayPTypes = [];
1580
        $arrayPModes = [];
1581
1582
        while (!$arrayTypes->EOF) {
1583
            $arrayPTypes[] = "'" . $arrayTypes->fields['typname'] . "'";
1584
            $arrayTypes->MoveNext();
1585
        }
1586
1587
        foreach ($arrayModes as $pV) {
1588
            $arrayPModes[] = \sprintf(
1589
                '\'%s\'',
1590
                $pV
1591
            );
1592
        }
1593
1594
        $szTypes = 'g_main_types = new Array(' . \implode(',', $arrayPTypes) . ');';
1595
        $szModes = 'g_main_modes = new Array(' . \implode(',', $arrayPModes) . ');';
1596
1597
        return $szTypes . $szModes;
1598
    }
1599
1600
    /**
1601
     * Get the concatenated arguments for a function.
1602
     *
1603
     * @param ADORecordSet $funcdata The funcdata record
1604
     *
1605
     * @return string The arguments of the function
1606
     */
1607
    private function _getPropertiesArgs($funcdata)
1608
    {
1609
        $data = $this->misc->getDatabaseAccessor();
1610
1611
        if ($data->hasNamedParams()) {
1612
            if (isset($funcdata->fields['proallarguments'])) {
1613
                $args_arr = $data->phpArray($funcdata->fields['proallarguments']);
1614
            } else {
1615
                $args_arr = \explode(', ', $funcdata->fields['proarguments']);
1616
            }
1617
            $names_arr = $data->phpArray($funcdata->fields['proargnames']);
1618
            $modes_arr = $data->phpArray($funcdata->fields['proargmodes']);
1619
            $args = '';
1620
            $args_arr_size = \count($args_arr);
1621
1622
            for ($i = 0; $i < $args_arr_size; ++$i) {
1623
                if (0 !== $i) {
1624
                    $args .= ', ';
1625
                }
1626
1627
                if (isset($modes_arr[$i])) {
1628
                    switch ($modes_arr[$i]) {
1629
                        case 'i':
1630
                            $args .= ' IN ';
1631
1632
                            break;
1633
                        case 'o':
1634
                            $args .= ' OUT ';
1635
1636
                            break;
1637
                        case 'b':
1638
                            $args .= ' INOUT ';
1639
1640
                            break;
1641
                        case 'v':
1642
                            $args .= ' VARIADIC ';
1643
1644
                            break;
1645
                        case 't':
1646
                            $args .= ' TABLE ';
1647
1648
                            break;
1649
                    }
1650
                }
1651
1652
                if (isset($names_arr[$i]) && '' !== $names_arr[$i]) {
1653
                    $data->fieldClean($names_arr[$i]);
1654
                    $args .= '"' . $names_arr[$i] . '" ';
1655
                }
1656
                $args .= $args_arr[$i];
1657
            }
1658
        } else {
1659
            $args = $funcdata->fields['proarguments'];
1660
        }
1661
1662
        return $args;
1663
    }
1664
}
1665